xref: /illumos-gate/usr/src/uts/common/io/comstar/stmf/stmf.c (revision ae127fcdca8de98fa8fff131c0002de8f24a79e0)
1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
2161dfa509SRick McNeal 
22fcf3ce44SJohn Forte /*
233fb517f7SJames Moore  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24fcf3ce44SJohn Forte  */
256ac72a9cSAlexander Stetsenko /*
2661dfa509SRick McNeal  * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
27a49dc893SSaso Kiselkov  * Copyright (c) 2013 by Delphix. All rights reserved.
28a49dc893SSaso Kiselkov  * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
296ac72a9cSAlexander Stetsenko  */
30fcf3ce44SJohn Forte 
31fcf3ce44SJohn Forte #include <sys/conf.h>
32fcf3ce44SJohn Forte #include <sys/file.h>
33fcf3ce44SJohn Forte #include <sys/ddi.h>
34fcf3ce44SJohn Forte #include <sys/sunddi.h>
35fcf3ce44SJohn Forte #include <sys/modctl.h>
36fcf3ce44SJohn Forte #include <sys/scsi/scsi.h>
37716c1805SNattuvetty Bhavyan #include <sys/scsi/generic/persist.h>
38fcf3ce44SJohn Forte #include <sys/scsi/impl/scsi_reset_notify.h>
39fcf3ce44SJohn Forte #include <sys/disp.h>
40fcf3ce44SJohn Forte #include <sys/byteorder.h>
41fcf3ce44SJohn Forte #include <sys/atomic.h>
42fcf3ce44SJohn Forte #include <sys/ethernet.h>
43fcf3ce44SJohn Forte #include <sys/sdt.h>
44fcf3ce44SJohn Forte #include <sys/nvpair.h>
455679c89fSjv227347 #include <sys/zone.h>
46427fcaf8Stim szeto #include <sys/id_space.h>
47fcf3ce44SJohn Forte 
484558d122SViswanathan Kannappan #include <sys/stmf.h>
494558d122SViswanathan Kannappan #include <sys/lpif.h>
504558d122SViswanathan Kannappan #include <sys/portif.h>
514558d122SViswanathan Kannappan #include <sys/stmf_ioctl.h>
524558d122SViswanathan Kannappan #include <sys/pppt_ic_if.h>
534558d122SViswanathan Kannappan 
544558d122SViswanathan Kannappan #include "stmf_impl.h"
554558d122SViswanathan Kannappan #include "lun_map.h"
564558d122SViswanathan Kannappan #include "stmf_state.h"
574558d122SViswanathan Kannappan #include "stmf_stats.h"
58fcf3ce44SJohn Forte 
59780c822cStim szeto /*
60780c822cStim szeto  * Lock order:
61780c822cStim szeto  * stmf_state_lock --> ilport_lock/iss_lockp --> ilu_task_lock
62780c822cStim szeto  */
63780c822cStim szeto 
64fcf3ce44SJohn Forte static uint64_t stmf_session_counter = 0;
65fcf3ce44SJohn Forte static uint16_t stmf_rtpid_counter = 0;
6645039663SJohn Forte /* start messages at 1 */
6745039663SJohn Forte static uint64_t stmf_proxy_msg_id = 1;
68cbdc6dc7SJohn Forte #define	MSG_ID_TM_BIT	0x8000000000000000
69716c1805SNattuvetty Bhavyan #define	ALIGNED_TO_8BYTE_BOUNDARY(i)	(((i) + 7) & ~7)
70fcf3ce44SJohn Forte 
71a49dc893SSaso Kiselkov /*
72a49dc893SSaso Kiselkov  * When stmf_io_deadman_enabled is set to B_TRUE, we check that finishing up
73a49dc893SSaso Kiselkov  * I/O operations on an offlining LU doesn't take longer than stmf_io_deadman
74a49dc893SSaso Kiselkov  * seconds. If it does, we trigger a panic to inform the user of hung I/O
75a49dc893SSaso Kiselkov  * blocking us for too long.
76a49dc893SSaso Kiselkov  */
77a49dc893SSaso Kiselkov boolean_t stmf_io_deadman_enabled = B_TRUE;
78a49dc893SSaso Kiselkov int stmf_io_deadman = 1000;			/* seconds */
79a49dc893SSaso Kiselkov 
80042f029eSAlexander Stetsenko struct stmf_svc_clocks;
81042f029eSAlexander Stetsenko 
82fcf3ce44SJohn Forte static int stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
83fcf3ce44SJohn Forte static int stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
84fcf3ce44SJohn Forte static int stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
85fcf3ce44SJohn Forte 	void **result);
86fcf3ce44SJohn Forte static int stmf_open(dev_t *devp, int flag, int otype, cred_t *credp);
87fcf3ce44SJohn Forte static int stmf_close(dev_t dev, int flag, int otype, cred_t *credp);
88fcf3ce44SJohn Forte static int stmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
89fcf3ce44SJohn Forte 	cred_t *credp, int *rval);
90fcf3ce44SJohn Forte static int stmf_get_stmf_state(stmf_state_desc_t *std);
91fcf3ce44SJohn Forte static int stmf_set_stmf_state(stmf_state_desc_t *std);
92fcf3ce44SJohn Forte static void stmf_abort_task_offline(scsi_task_t *task, int offline_lu,
93fcf3ce44SJohn Forte     char *info);
9445039663SJohn Forte static int stmf_set_alua_state(stmf_alua_state_desc_t *alua_state);
9545039663SJohn Forte static void stmf_get_alua_state(stmf_alua_state_desc_t *alua_state);
9640c3e8ffSJohn Forte 
9740c3e8ffSJohn Forte static void stmf_task_audit(stmf_i_scsi_task_t *itask,
9840c3e8ffSJohn Forte     task_audit_event_t te, uint32_t cmd_or_iof, stmf_data_buf_t *dbuf);
9940c3e8ffSJohn Forte 
100716c1805SNattuvetty Bhavyan static boolean_t stmf_base16_str_to_binary(char *c, int dplen, uint8_t *dp);
101716c1805SNattuvetty Bhavyan static char stmf_ctoi(char c);
10245039663SJohn Forte stmf_xfer_data_t *stmf_prepare_tpgs_data(uint8_t ilu_alua);
103fcf3ce44SJohn Forte void stmf_svc_init();
104fcf3ce44SJohn Forte stmf_status_t stmf_svc_fini();
105fcf3ce44SJohn Forte void stmf_svc(void *arg);
106a49dc893SSaso Kiselkov static void stmf_wait_ilu_tasks_finish(stmf_i_lu_t *ilu);
107fcf3ce44SJohn Forte void stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info);
1086ac72a9cSAlexander Stetsenko static void stmf_svc_kill_obj_requests(void *obj);
109042f029eSAlexander Stetsenko static void stmf_svc_timeout(struct stmf_svc_clocks *);
110fcf3ce44SJohn Forte void stmf_check_freetask();
111fcf3ce44SJohn Forte void stmf_abort_target_reset(scsi_task_t *task);
112fcf3ce44SJohn Forte stmf_status_t stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task,
113fcf3ce44SJohn Forte 							int target_reset);
114fcf3ce44SJohn Forte void stmf_target_reset_poll(struct scsi_task *task);
115fcf3ce44SJohn Forte void stmf_handle_lun_reset(scsi_task_t *task);
116fcf3ce44SJohn Forte void stmf_handle_target_reset(scsi_task_t *task);
11791159e90SJohn Forte void stmf_xd_to_dbuf(stmf_data_buf_t *dbuf, int set_rel_off);
1188fe96085Stim szeto int stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
1198fe96085Stim szeto     uint32_t *err_ret);
120fcf3ce44SJohn Forte int stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi);
1218fe96085Stim szeto int stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
1228fe96085Stim szeto     uint32_t *err_ret);
123fcf3ce44SJohn Forte void stmf_delete_ppd(stmf_pp_data_t *ppd);
124fcf3ce44SJohn Forte void stmf_delete_all_ppds();
125fcf3ce44SJohn Forte void stmf_trace_clear();
126fcf3ce44SJohn Forte void stmf_worker_init();
127fcf3ce44SJohn Forte stmf_status_t stmf_worker_fini();
128fcf3ce44SJohn Forte void stmf_worker_task(void *arg);
12945039663SJohn Forte static void stmf_task_lu_free(scsi_task_t *task, stmf_i_scsi_session_t *iss);
13045039663SJohn Forte static stmf_status_t stmf_ic_lu_reg(stmf_ic_reg_dereg_lun_msg_t *msg,
13145039663SJohn Forte     uint32_t type);
13245039663SJohn Forte static stmf_status_t stmf_ic_lu_dereg(stmf_ic_reg_dereg_lun_msg_t *msg);
13345039663SJohn Forte static stmf_status_t stmf_ic_rx_scsi_status(stmf_ic_scsi_status_msg_t *msg);
13445039663SJohn Forte static stmf_status_t stmf_ic_rx_status(stmf_ic_status_msg_t *msg);
13545039663SJohn Forte static stmf_status_t stmf_ic_rx_scsi_data(stmf_ic_scsi_data_msg_t *msg);
13645039663SJohn Forte void stmf_task_lu_killall(stmf_lu_t *lu, scsi_task_t *tm_task, stmf_status_t s);
13745039663SJohn Forte 
13845039663SJohn Forte /* pppt modhandle */
13945039663SJohn Forte ddi_modhandle_t pppt_mod;
14045039663SJohn Forte 
14145039663SJohn Forte /* pppt modload imported functions */
14245039663SJohn Forte stmf_ic_reg_port_msg_alloc_func_t ic_reg_port_msg_alloc;
14345039663SJohn Forte stmf_ic_dereg_port_msg_alloc_func_t ic_dereg_port_msg_alloc;
14445039663SJohn Forte stmf_ic_reg_lun_msg_alloc_func_t ic_reg_lun_msg_alloc;
14545039663SJohn Forte stmf_ic_dereg_lun_msg_alloc_func_t ic_dereg_lun_msg_alloc;
14645039663SJohn Forte stmf_ic_lun_active_msg_alloc_func_t ic_lun_active_msg_alloc;
14745039663SJohn Forte stmf_ic_scsi_cmd_msg_alloc_func_t ic_scsi_cmd_msg_alloc;
14845039663SJohn Forte stmf_ic_scsi_data_xfer_done_msg_alloc_func_t ic_scsi_data_xfer_done_msg_alloc;
14945039663SJohn Forte stmf_ic_session_create_msg_alloc_func_t ic_session_reg_msg_alloc;
15045039663SJohn Forte stmf_ic_session_destroy_msg_alloc_func_t ic_session_dereg_msg_alloc;
15145039663SJohn Forte stmf_ic_tx_msg_func_t ic_tx_msg;
15245039663SJohn Forte stmf_ic_msg_free_func_t ic_msg_free;
153fcf3ce44SJohn Forte 
154427fcaf8Stim szeto static void stmf_itl_task_start(stmf_i_scsi_task_t *itask);
155427fcaf8Stim szeto static void stmf_itl_lu_new_task(stmf_i_scsi_task_t *itask);
156427fcaf8Stim szeto static void stmf_itl_task_done(stmf_i_scsi_task_t *itask);
157427fcaf8Stim szeto 
158427fcaf8Stim szeto static void stmf_lport_xfer_start(stmf_i_scsi_task_t *itask,
159427fcaf8Stim szeto     stmf_data_buf_t *dbuf);
160427fcaf8Stim szeto static void stmf_lport_xfer_done(stmf_i_scsi_task_t *itask,
161427fcaf8Stim szeto     stmf_data_buf_t *dbuf);
162427fcaf8Stim szeto 
163034d83c4Stim szeto static void stmf_update_kstat_lu_q(scsi_task_t *, void());
164034d83c4Stim szeto static void stmf_update_kstat_lport_q(scsi_task_t *, void());
165034d83c4Stim szeto static void stmf_update_kstat_lu_io(scsi_task_t *, stmf_data_buf_t *);
166034d83c4Stim szeto static void stmf_update_kstat_lport_io(scsi_task_t *, stmf_data_buf_t *);
16761dfa509SRick McNeal static hrtime_t stmf_update_rport_timestamps(hrtime_t *start_tstamp,
16861dfa509SRick McNeal     hrtime_t *done_tstamp, stmf_i_scsi_task_t *itask);
169034d83c4Stim szeto 
170427fcaf8Stim szeto static int stmf_irport_compare(const void *void_irport1,
171427fcaf8Stim szeto     const void *void_irport2);
17261dfa509SRick McNeal static void stmf_create_kstat_rport(stmf_i_remote_port_t *irport);
17361dfa509SRick McNeal static void stmf_destroy_kstat_rport(stmf_i_remote_port_t *irport);
17461dfa509SRick McNeal static int stmf_kstat_rport_update(kstat_t *ksp, int rw);
175427fcaf8Stim szeto static stmf_i_remote_port_t *stmf_irport_create(scsi_devid_desc_t *rport_devid);
176427fcaf8Stim szeto static void stmf_irport_destroy(stmf_i_remote_port_t *irport);
177427fcaf8Stim szeto static stmf_i_remote_port_t *stmf_irport_register(
178427fcaf8Stim szeto     scsi_devid_desc_t *rport_devid);
179427fcaf8Stim szeto static stmf_i_remote_port_t *stmf_irport_lookup_locked(
180427fcaf8Stim szeto     scsi_devid_desc_t *rport_devid);
181427fcaf8Stim szeto static void stmf_irport_deregister(stmf_i_remote_port_t *irport);
182427fcaf8Stim szeto 
183fcf3ce44SJohn Forte extern struct mod_ops mod_driverops;
184fcf3ce44SJohn Forte 
185fcf3ce44SJohn Forte /* =====[ Tunables ]===== */
186fcf3ce44SJohn Forte /* Internal tracing */
18761dfa509SRick McNeal volatile int	stmf_trace_on = 0;
188fcf3ce44SJohn Forte volatile int	stmf_trace_buf_size = (1 * 1024 * 1024);
189fcf3ce44SJohn Forte /*
190fcf3ce44SJohn Forte  * The reason default task timeout is 75 is because we want the
191fcf3ce44SJohn Forte  * host to timeout 1st and mostly host timeout is 60 seconds.
192fcf3ce44SJohn Forte  */
193fcf3ce44SJohn Forte volatile int	stmf_default_task_timeout = 75;
194fcf3ce44SJohn Forte /*
195fcf3ce44SJohn Forte  * Setting this to one means, you are responsible for config load and keeping
196fcf3ce44SJohn Forte  * things in sync with persistent database.
197fcf3ce44SJohn Forte  */
198fcf3ce44SJohn Forte volatile int	stmf_allow_modunload = 0;
199fcf3ce44SJohn Forte 
20061dfa509SRick McNeal volatile int stmf_nworkers = 512;
201fcf3ce44SJohn Forte 
202fcf3ce44SJohn Forte /* === [ Debugging and fault injection ] === */
203fcf3ce44SJohn Forte #ifdef	DEBUG
20461dfa509SRick McNeal volatile int stmf_drop_task_counter = 0;
20561dfa509SRick McNeal volatile int stmf_drop_buf_counter = 0;
206fcf3ce44SJohn Forte 
207fcf3ce44SJohn Forte #endif
208fcf3ce44SJohn Forte 
209fcf3ce44SJohn Forte stmf_state_t		stmf_state;
210fcf3ce44SJohn Forte static stmf_lu_t	*dlun0;
211fcf3ce44SJohn Forte 
212fcf3ce44SJohn Forte static uint8_t stmf_first_zero[] =
213fcf3ce44SJohn Forte 	{ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0xff };
214fcf3ce44SJohn Forte static uint8_t stmf_first_one[] =
215fcf3ce44SJohn Forte 	{ 0xff, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
216fcf3ce44SJohn Forte 
217fcf3ce44SJohn Forte static kmutex_t	trace_buf_lock;
218fcf3ce44SJohn Forte static int	trace_buf_size;
219fcf3ce44SJohn Forte static int	trace_buf_curndx;
220fcf3ce44SJohn Forte caddr_t	stmf_trace_buf;
221fcf3ce44SJohn Forte 
222fcf3ce44SJohn Forte static enum {
223fcf3ce44SJohn Forte 	STMF_WORKERS_DISABLED = 0,
224fcf3ce44SJohn Forte 	STMF_WORKERS_ENABLING,
225fcf3ce44SJohn Forte 	STMF_WORKERS_ENABLED
226fcf3ce44SJohn Forte } stmf_workers_state = STMF_WORKERS_DISABLED;
22761dfa509SRick McNeal static kmutex_t	stmf_worker_sel_mx;
22861dfa509SRick McNeal volatile uint32_t stmf_nworkers_cur = 0; /* # of workers currently running */
229fcf3ce44SJohn Forte static int stmf_worker_sel_counter = 0;
230fcf3ce44SJohn Forte static uint32_t stmf_cur_ntasks = 0;
23161dfa509SRick McNeal static clock_t stmf_wm_next = 0;
232fcf3ce44SJohn Forte static int stmf_nworkers_accepting_cmds;
233fcf3ce44SJohn Forte static stmf_worker_t *stmf_workers = NULL;
234fcf3ce44SJohn Forte static clock_t stmf_worker_scale_down_timer = 0;
235fcf3ce44SJohn Forte static int stmf_worker_scale_down_qd = 0;
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte static struct cb_ops stmf_cb_ops = {
238fcf3ce44SJohn Forte 	stmf_open,			/* open */
239fcf3ce44SJohn Forte 	stmf_close,			/* close */
240fcf3ce44SJohn Forte 	nodev,				/* strategy */
241fcf3ce44SJohn Forte 	nodev,				/* print */
242fcf3ce44SJohn Forte 	nodev,				/* dump */
243fcf3ce44SJohn Forte 	nodev,				/* read */
244fcf3ce44SJohn Forte 	nodev,				/* write */
245fcf3ce44SJohn Forte 	stmf_ioctl,			/* ioctl */
246fcf3ce44SJohn Forte 	nodev,				/* devmap */
247fcf3ce44SJohn Forte 	nodev,				/* mmap */
248fcf3ce44SJohn Forte 	nodev,				/* segmap */
249fcf3ce44SJohn Forte 	nochpoll,			/* chpoll */
250fcf3ce44SJohn Forte 	ddi_prop_op,			/* cb_prop_op */
251fcf3ce44SJohn Forte 	0,				/* streamtab */
252fcf3ce44SJohn Forte 	D_NEW | D_MP,			/* cb_flag */
253fcf3ce44SJohn Forte 	CB_REV,				/* rev */
254fcf3ce44SJohn Forte 	nodev,				/* aread */
255fcf3ce44SJohn Forte 	nodev				/* awrite */
256fcf3ce44SJohn Forte };
257fcf3ce44SJohn Forte 
258fcf3ce44SJohn Forte static struct dev_ops stmf_ops = {
259fcf3ce44SJohn Forte 	DEVO_REV,
260fcf3ce44SJohn Forte 	0,
261fcf3ce44SJohn Forte 	stmf_getinfo,
262fcf3ce44SJohn Forte 	nulldev,		/* identify */
263fcf3ce44SJohn Forte 	nulldev,		/* probe */
264fcf3ce44SJohn Forte 	stmf_attach,
265fcf3ce44SJohn Forte 	stmf_detach,
266fcf3ce44SJohn Forte 	nodev,			/* reset */
267fcf3ce44SJohn Forte 	&stmf_cb_ops,
268fcf3ce44SJohn Forte 	NULL,			/* bus_ops */
269fcf3ce44SJohn Forte 	NULL			/* power */
270fcf3ce44SJohn Forte };
271fcf3ce44SJohn Forte 
272fcf3ce44SJohn Forte #define	STMF_NAME		"COMSTAR STMF"
273034d83c4Stim szeto #define	STMF_MODULE_NAME	"stmf"
274fcf3ce44SJohn Forte 
275fcf3ce44SJohn Forte static struct modldrv modldrv = {
276fcf3ce44SJohn Forte 	&mod_driverops,
277fcf3ce44SJohn Forte 	STMF_NAME,
278fcf3ce44SJohn Forte 	&stmf_ops
279fcf3ce44SJohn Forte };
280fcf3ce44SJohn Forte 
281fcf3ce44SJohn Forte static struct modlinkage modlinkage = {
282fcf3ce44SJohn Forte 	MODREV_1,
283fcf3ce44SJohn Forte 	&modldrv,
284fcf3ce44SJohn Forte 	NULL
285fcf3ce44SJohn Forte };
286fcf3ce44SJohn Forte 
287fcf3ce44SJohn Forte int
_init(void)288fcf3ce44SJohn Forte _init(void)
289fcf3ce44SJohn Forte {
290fcf3ce44SJohn Forte 	int ret;
291fcf3ce44SJohn Forte 
292fcf3ce44SJohn Forte 	ret = mod_install(&modlinkage);
293fcf3ce44SJohn Forte 	if (ret)
294fcf3ce44SJohn Forte 		return (ret);
295fcf3ce44SJohn Forte 	stmf_trace_buf = kmem_zalloc(stmf_trace_buf_size, KM_SLEEP);
296fcf3ce44SJohn Forte 	trace_buf_size = stmf_trace_buf_size;
297fcf3ce44SJohn Forte 	trace_buf_curndx = 0;
298fcf3ce44SJohn Forte 	mutex_init(&trace_buf_lock, NULL, MUTEX_DRIVER, 0);
29961dfa509SRick McNeal 	mutex_init(&stmf_worker_sel_mx, NULL, MUTEX_ADAPTIVE, 0);
300fcf3ce44SJohn Forte 	bzero(&stmf_state, sizeof (stmf_state_t));
301fcf3ce44SJohn Forte 	/* STMF service is off by default */
302fcf3ce44SJohn Forte 	stmf_state.stmf_service_running = 0;
3034b31676fSsrivijitha dugganapalli 	/* default lu/lport states are online */
3044b31676fSsrivijitha dugganapalli 	stmf_state.stmf_default_lu_state = STMF_STATE_ONLINE;
3054b31676fSsrivijitha dugganapalli 	stmf_state.stmf_default_lport_state = STMF_STATE_ONLINE;
306fcf3ce44SJohn Forte 	mutex_init(&stmf_state.stmf_lock, NULL, MUTEX_DRIVER, NULL);
307fcf3ce44SJohn Forte 	cv_init(&stmf_state.stmf_cv, NULL, CV_DRIVER, NULL);
308fcf3ce44SJohn Forte 	stmf_session_counter = (uint64_t)ddi_get_lbolt();
309427fcaf8Stim szeto 	avl_create(&stmf_state.stmf_irportlist,
310427fcaf8Stim szeto 	    stmf_irport_compare, sizeof (stmf_i_remote_port_t),
311427fcaf8Stim szeto 	    offsetof(stmf_i_remote_port_t, irport_ln));
312427fcaf8Stim szeto 	stmf_state.stmf_ilport_inst_space =
313427fcaf8Stim szeto 	    id_space_create("lport-instances", 0, MAX_ILPORT);
314427fcaf8Stim szeto 	stmf_state.stmf_irport_inst_space =
315427fcaf8Stim szeto 	    id_space_create("rport-instances", 0, MAX_IRPORT);
316fcf3ce44SJohn Forte 	stmf_view_init();
317fcf3ce44SJohn Forte 	stmf_svc_init();
318fcf3ce44SJohn Forte 	stmf_dlun_init();
319fcf3ce44SJohn Forte 	return (ret);
320fcf3ce44SJohn Forte }
321fcf3ce44SJohn Forte 
322fcf3ce44SJohn Forte int
_fini(void)323fcf3ce44SJohn Forte _fini(void)
324fcf3ce44SJohn Forte {
325fcf3ce44SJohn Forte 	int ret;
326427fcaf8Stim szeto 	stmf_i_remote_port_t	*irport;
327427fcaf8Stim szeto 	void			*avl_dest_cookie = NULL;
328fcf3ce44SJohn Forte 
329fcf3ce44SJohn Forte 	if (stmf_state.stmf_service_running)
330fcf3ce44SJohn Forte 		return (EBUSY);
331fcf3ce44SJohn Forte 	if ((!stmf_allow_modunload) &&
332fcf3ce44SJohn Forte 	    (stmf_state.stmf_config_state != STMF_CONFIG_NONE)) {
333fcf3ce44SJohn Forte 		return (EBUSY);
334fcf3ce44SJohn Forte 	}
335fcf3ce44SJohn Forte 	if (stmf_state.stmf_nlps || stmf_state.stmf_npps) {
336fcf3ce44SJohn Forte 		return (EBUSY);
337fcf3ce44SJohn Forte 	}
338fcf3ce44SJohn Forte 	if (stmf_dlun_fini() != STMF_SUCCESS)
339fcf3ce44SJohn Forte 		return (EBUSY);
340fcf3ce44SJohn Forte 	if (stmf_worker_fini() != STMF_SUCCESS) {
341fcf3ce44SJohn Forte 		stmf_dlun_init();
342fcf3ce44SJohn Forte 		return (EBUSY);
343fcf3ce44SJohn Forte 	}
344fcf3ce44SJohn Forte 	if (stmf_svc_fini() != STMF_SUCCESS) {
345fcf3ce44SJohn Forte 		stmf_dlun_init();
346fcf3ce44SJohn Forte 		stmf_worker_init();
347fcf3ce44SJohn Forte 		return (EBUSY);
348fcf3ce44SJohn Forte 	}
349fcf3ce44SJohn Forte 
350fcf3ce44SJohn Forte 	ret = mod_remove(&modlinkage);
351fcf3ce44SJohn Forte 	if (ret) {
352fcf3ce44SJohn Forte 		stmf_svc_init();
353fcf3ce44SJohn Forte 		stmf_dlun_init();
354fcf3ce44SJohn Forte 		stmf_worker_init();
355fcf3ce44SJohn Forte 		return (ret);
356fcf3ce44SJohn Forte 	}
357fcf3ce44SJohn Forte 
358fcf3ce44SJohn Forte 	stmf_view_clear_config();
359427fcaf8Stim szeto 
360427fcaf8Stim szeto 	while ((irport = avl_destroy_nodes(&stmf_state.stmf_irportlist,
361427fcaf8Stim szeto 	    &avl_dest_cookie)) != NULL)
362427fcaf8Stim szeto 		stmf_irport_destroy(irport);
363427fcaf8Stim szeto 	avl_destroy(&stmf_state.stmf_irportlist);
364427fcaf8Stim szeto 	id_space_destroy(stmf_state.stmf_ilport_inst_space);
365427fcaf8Stim szeto 	id_space_destroy(stmf_state.stmf_irport_inst_space);
366427fcaf8Stim szeto 
367fcf3ce44SJohn Forte 	kmem_free(stmf_trace_buf, stmf_trace_buf_size);
368fcf3ce44SJohn Forte 	mutex_destroy(&trace_buf_lock);
369fcf3ce44SJohn Forte 	mutex_destroy(&stmf_state.stmf_lock);
37061dfa509SRick McNeal 	mutex_destroy(&stmf_worker_sel_mx);
371fcf3ce44SJohn Forte 	cv_destroy(&stmf_state.stmf_cv);
372fcf3ce44SJohn Forte 	return (ret);
373fcf3ce44SJohn Forte }
374fcf3ce44SJohn Forte 
375fcf3ce44SJohn Forte int
_info(struct modinfo * modinfop)376fcf3ce44SJohn Forte _info(struct modinfo *modinfop)
377fcf3ce44SJohn Forte {
378fcf3ce44SJohn Forte 	return (mod_info(&modlinkage, modinfop));
379fcf3ce44SJohn Forte }
380fcf3ce44SJohn Forte 
381fcf3ce44SJohn Forte /* ARGSUSED */
382fcf3ce44SJohn Forte static int
stmf_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)383fcf3ce44SJohn Forte stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
384fcf3ce44SJohn Forte {
385fcf3ce44SJohn Forte 	switch (cmd) {
386fcf3ce44SJohn Forte 	case DDI_INFO_DEVT2DEVINFO:
387fcf3ce44SJohn Forte 		*result = stmf_state.stmf_dip;
388fcf3ce44SJohn Forte 		break;
389fcf3ce44SJohn Forte 	case DDI_INFO_DEVT2INSTANCE:
3908fe96085Stim szeto 		*result =
3918fe96085Stim szeto 		    (void *)(uintptr_t)ddi_get_instance(stmf_state.stmf_dip);
392fcf3ce44SJohn Forte 		break;
393fcf3ce44SJohn Forte 	default:
394fcf3ce44SJohn Forte 		return (DDI_FAILURE);
395fcf3ce44SJohn Forte 	}
396fcf3ce44SJohn Forte 
397fcf3ce44SJohn Forte 	return (DDI_SUCCESS);
398fcf3ce44SJohn Forte }
399fcf3ce44SJohn Forte 
400fcf3ce44SJohn Forte static int
stmf_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)401fcf3ce44SJohn Forte stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
402fcf3ce44SJohn Forte {
403fcf3ce44SJohn Forte 	switch (cmd) {
404fcf3ce44SJohn Forte 	case DDI_ATTACH:
405fcf3ce44SJohn Forte 		stmf_state.stmf_dip = dip;
406fcf3ce44SJohn Forte 
407fcf3ce44SJohn Forte 		if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
408fcf3ce44SJohn Forte 		    DDI_NT_STMF, 0) != DDI_SUCCESS) {
409fcf3ce44SJohn Forte 			break;
410fcf3ce44SJohn Forte 		}
411fcf3ce44SJohn Forte 		ddi_report_dev(dip);
412fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
413fcf3ce44SJohn Forte 	}
414fcf3ce44SJohn Forte 
415fcf3ce44SJohn Forte 	return (DDI_FAILURE);
416fcf3ce44SJohn Forte }
417fcf3ce44SJohn Forte 
418fcf3ce44SJohn Forte static int
stmf_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)419fcf3ce44SJohn Forte stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
420fcf3ce44SJohn Forte {
421fcf3ce44SJohn Forte 	switch (cmd) {
422fcf3ce44SJohn Forte 	case DDI_DETACH:
423fcf3ce44SJohn Forte 		ddi_remove_minor_node(dip, 0);
424fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
425fcf3ce44SJohn Forte 	}
426fcf3ce44SJohn Forte 
427fcf3ce44SJohn Forte 	return (DDI_FAILURE);
428fcf3ce44SJohn Forte }
429fcf3ce44SJohn Forte 
430fcf3ce44SJohn Forte /* ARGSUSED */
431fcf3ce44SJohn Forte static int
stmf_open(dev_t * devp,int flag,int otype,cred_t * credp)432fcf3ce44SJohn Forte stmf_open(dev_t *devp, int flag, int otype, cred_t *credp)
433fcf3ce44SJohn Forte {
434fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
435fcf3ce44SJohn Forte 	if (stmf_state.stmf_exclusive_open) {
436fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
437fcf3ce44SJohn Forte 		return (EBUSY);
438fcf3ce44SJohn Forte 	}
439fcf3ce44SJohn Forte 	if (flag & FEXCL) {
440fcf3ce44SJohn Forte 		if (stmf_state.stmf_opened) {
441fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
442fcf3ce44SJohn Forte 			return (EBUSY);
443fcf3ce44SJohn Forte 		}
444fcf3ce44SJohn Forte 		stmf_state.stmf_exclusive_open = 1;
445fcf3ce44SJohn Forte 	}
446fcf3ce44SJohn Forte 	stmf_state.stmf_opened = 1;
447fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
448fcf3ce44SJohn Forte 	return (0);
449fcf3ce44SJohn Forte }
450fcf3ce44SJohn Forte 
451fcf3ce44SJohn Forte /* ARGSUSED */
452fcf3ce44SJohn Forte static int
stmf_close(dev_t dev,int flag,int otype,cred_t * credp)453fcf3ce44SJohn Forte stmf_close(dev_t dev, int flag, int otype, cred_t *credp)
454fcf3ce44SJohn Forte {
455fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
456fcf3ce44SJohn Forte 	stmf_state.stmf_opened = 0;
457fcf3ce44SJohn Forte 	if (stmf_state.stmf_exclusive_open &&
458fcf3ce44SJohn Forte 	    (stmf_state.stmf_config_state != STMF_CONFIG_INIT_DONE)) {
459fcf3ce44SJohn Forte 		stmf_state.stmf_config_state = STMF_CONFIG_NONE;
460fcf3ce44SJohn Forte 		stmf_delete_all_ppds();
461fcf3ce44SJohn Forte 		stmf_view_clear_config();
462fcf3ce44SJohn Forte 		stmf_view_init();
463fcf3ce44SJohn Forte 	}
464fcf3ce44SJohn Forte 	stmf_state.stmf_exclusive_open = 0;
465fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
466fcf3ce44SJohn Forte 	return (0);
467fcf3ce44SJohn Forte }
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte int
stmf_copyin_iocdata(intptr_t data,int mode,stmf_iocdata_t ** iocd,void ** ibuf,void ** obuf)470fcf3ce44SJohn Forte stmf_copyin_iocdata(intptr_t data, int mode, stmf_iocdata_t **iocd,
471fcf3ce44SJohn Forte     void **ibuf, void **obuf)
472fcf3ce44SJohn Forte {
473fcf3ce44SJohn Forte 	int ret;
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte 	*ibuf = NULL;
476fcf3ce44SJohn Forte 	*obuf = NULL;
477fcf3ce44SJohn Forte 	*iocd = kmem_zalloc(sizeof (stmf_iocdata_t), KM_SLEEP);
478fcf3ce44SJohn Forte 
479fcf3ce44SJohn Forte 	ret = ddi_copyin((void *)data, *iocd, sizeof (stmf_iocdata_t), mode);
480fcf3ce44SJohn Forte 	if (ret)
481fcf3ce44SJohn Forte 		return (EFAULT);
482fcf3ce44SJohn Forte 	if ((*iocd)->stmf_version != STMF_VERSION_1) {
483fcf3ce44SJohn Forte 		ret = EINVAL;
484fcf3ce44SJohn Forte 		goto copyin_iocdata_done;
485fcf3ce44SJohn Forte 	}
486fcf3ce44SJohn Forte 	if ((*iocd)->stmf_ibuf_size) {
487fcf3ce44SJohn Forte 		*ibuf = kmem_zalloc((*iocd)->stmf_ibuf_size, KM_SLEEP);
488fcf3ce44SJohn Forte 		ret = ddi_copyin((void *)((unsigned long)(*iocd)->stmf_ibuf),
489fcf3ce44SJohn Forte 		    *ibuf, (*iocd)->stmf_ibuf_size, mode);
490fcf3ce44SJohn Forte 	}
491fcf3ce44SJohn Forte 	if ((*iocd)->stmf_obuf_size)
492fcf3ce44SJohn Forte 		*obuf = kmem_zalloc((*iocd)->stmf_obuf_size, KM_SLEEP);
493fcf3ce44SJohn Forte 
494fcf3ce44SJohn Forte 	if (ret == 0)
495fcf3ce44SJohn Forte 		return (0);
496fcf3ce44SJohn Forte 	ret = EFAULT;
497fcf3ce44SJohn Forte copyin_iocdata_done:;
498fcf3ce44SJohn Forte 	if (*obuf) {
499fcf3ce44SJohn Forte 		kmem_free(*obuf, (*iocd)->stmf_obuf_size);
500fcf3ce44SJohn Forte 		*obuf = NULL;
501fcf3ce44SJohn Forte 	}
502fcf3ce44SJohn Forte 	if (*ibuf) {
503fcf3ce44SJohn Forte 		kmem_free(*ibuf, (*iocd)->stmf_ibuf_size);
504fcf3ce44SJohn Forte 		*ibuf = NULL;
505fcf3ce44SJohn Forte 	}
506fcf3ce44SJohn Forte 	kmem_free(*iocd, sizeof (stmf_iocdata_t));
507fcf3ce44SJohn Forte 	return (ret);
508fcf3ce44SJohn Forte }
509fcf3ce44SJohn Forte 
510fcf3ce44SJohn Forte int
stmf_copyout_iocdata(intptr_t data,int mode,stmf_iocdata_t * iocd,void * obuf)511fcf3ce44SJohn Forte stmf_copyout_iocdata(intptr_t data, int mode, stmf_iocdata_t *iocd, void *obuf)
512fcf3ce44SJohn Forte {
513fcf3ce44SJohn Forte 	int ret;
514fcf3ce44SJohn Forte 
515fcf3ce44SJohn Forte 	if (iocd->stmf_obuf_size) {
516fcf3ce44SJohn Forte 		ret = ddi_copyout(obuf, (void *)(unsigned long)iocd->stmf_obuf,
517fcf3ce44SJohn Forte 		    iocd->stmf_obuf_size, mode);
518fcf3ce44SJohn Forte 		if (ret)
519fcf3ce44SJohn Forte 			return (EFAULT);
520fcf3ce44SJohn Forte 	}
521fcf3ce44SJohn Forte 	ret = ddi_copyout(iocd, (void *)data, sizeof (stmf_iocdata_t), mode);
522fcf3ce44SJohn Forte 	if (ret)
523fcf3ce44SJohn Forte 		return (EFAULT);
524fcf3ce44SJohn Forte 	return (0);
525fcf3ce44SJohn Forte }
526fcf3ce44SJohn Forte 
527fcf3ce44SJohn Forte /* ARGSUSED */
528fcf3ce44SJohn Forte static int
stmf_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * credp,int * rval)529fcf3ce44SJohn Forte stmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
530fcf3ce44SJohn Forte     cred_t *credp, int *rval)
531fcf3ce44SJohn Forte {
532fcf3ce44SJohn Forte 	stmf_iocdata_t *iocd;
533fcf3ce44SJohn Forte 	void *ibuf = NULL, *obuf = NULL;
534fcf3ce44SJohn Forte 	slist_lu_t *luid_list;
535fcf3ce44SJohn Forte 	slist_target_port_t *lportid_list;
536fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
537fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
538fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
539fcf3ce44SJohn Forte 	slist_scsi_session_t *iss_list;
540fcf3ce44SJohn Forte 	sioc_lu_props_t *lup;
541fcf3ce44SJohn Forte 	sioc_target_port_props_t *lportp;
5428fe96085Stim szeto 	stmf_ppioctl_data_t *ppi, *ppi_out = NULL;
5438fe96085Stim szeto 	uint64_t *ppi_token = NULL;
5448fe96085Stim szeto 	uint8_t *p_id, *id;
545fcf3ce44SJohn Forte 	stmf_state_desc_t *std;
546fcf3ce44SJohn Forte 	stmf_status_t ctl_ret;
547fcf3ce44SJohn Forte 	stmf_state_change_info_t ssi;
548fcf3ce44SJohn Forte 	int ret = 0;
549fcf3ce44SJohn Forte 	uint32_t n;
550fcf3ce44SJohn Forte 	int i;
551fcf3ce44SJohn Forte 	stmf_group_op_data_t *grp_entry;
552fcf3ce44SJohn Forte 	stmf_group_name_t *grpname;
553fcf3ce44SJohn Forte 	stmf_view_op_entry_t *ve;
554fcf3ce44SJohn Forte 	stmf_id_type_t idtype;
555fcf3ce44SJohn Forte 	stmf_id_data_t *id_entry;
556fcf3ce44SJohn Forte 	stmf_id_list_t	*id_list;
557fcf3ce44SJohn Forte 	stmf_view_entry_t *view_entry;
5584b31676fSsrivijitha dugganapalli 	stmf_set_props_t *stmf_set_props;
559fcf3ce44SJohn Forte 	uint32_t	veid;
560fcf3ce44SJohn Forte 	if ((cmd & 0xff000000) != STMF_IOCTL) {
561fcf3ce44SJohn Forte 		return (ENOTTY);
562fcf3ce44SJohn Forte 	}
563fcf3ce44SJohn Forte 
564fcf3ce44SJohn Forte 	if (drv_priv(credp) != 0) {
565fcf3ce44SJohn Forte 		return (EPERM);
566fcf3ce44SJohn Forte 	}
567fcf3ce44SJohn Forte 
568fcf3ce44SJohn Forte 	ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
569fcf3ce44SJohn Forte 	if (ret)
570fcf3ce44SJohn Forte 		return (ret);
571fcf3ce44SJohn Forte 	iocd->stmf_error = 0;
572fcf3ce44SJohn Forte 
573fcf3ce44SJohn Forte 	switch (cmd) {
574fcf3ce44SJohn Forte 	case STMF_IOCTL_LU_LIST:
5758fe96085Stim szeto 		/* retrieves both registered/unregistered */
5768fe96085Stim szeto 		mutex_enter(&stmf_state.stmf_lock);
5778fe96085Stim szeto 		id_list = &stmf_state.stmf_luid_list;
5788fe96085Stim szeto 		n = min(id_list->id_count,
5798fe96085Stim szeto 		    (iocd->stmf_obuf_size)/sizeof (slist_lu_t));
5808fe96085Stim szeto 		iocd->stmf_obuf_max_nentries = id_list->id_count;
5818fe96085Stim szeto 		luid_list = (slist_lu_t *)obuf;
5828fe96085Stim szeto 		id_entry = id_list->idl_head;
5838fe96085Stim szeto 		for (i = 0; i < n; i++) {
5848fe96085Stim szeto 			bcopy(id_entry->id_data, luid_list[i].lu_guid, 16);
5858fe96085Stim szeto 			id_entry = id_entry->id_next;
5868fe96085Stim szeto 		}
5878fe96085Stim szeto 
5888fe96085Stim szeto 		n = iocd->stmf_obuf_size/sizeof (slist_lu_t);
5898fe96085Stim szeto 		for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
5908fe96085Stim szeto 			id = (uint8_t *)ilu->ilu_lu->lu_id;
5918fe96085Stim szeto 			if (stmf_lookup_id(id_list, 16, id + 4) == NULL) {
5928fe96085Stim szeto 				iocd->stmf_obuf_max_nentries++;
5938fe96085Stim szeto 				if (i < n) {
5948fe96085Stim szeto 					bcopy(id + 4, luid_list[i].lu_guid,
5958fe96085Stim szeto 					    sizeof (slist_lu_t));
5968fe96085Stim szeto 					i++;
5978fe96085Stim szeto 				}
5988fe96085Stim szeto 			}
5998fe96085Stim szeto 		}
6008fe96085Stim szeto 		iocd->stmf_obuf_nentries = i;
6018fe96085Stim szeto 		mutex_exit(&stmf_state.stmf_lock);
6028fe96085Stim szeto 		break;
6038fe96085Stim szeto 
6048fe96085Stim szeto 	case STMF_IOCTL_REG_LU_LIST:
605fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
606fcf3ce44SJohn Forte 		iocd->stmf_obuf_max_nentries = stmf_state.stmf_nlus;
607fcf3ce44SJohn Forte 		n = min(stmf_state.stmf_nlus,
608fcf3ce44SJohn Forte 		    (iocd->stmf_obuf_size)/sizeof (slist_lu_t));
609fcf3ce44SJohn Forte 		iocd->stmf_obuf_nentries = n;
610fcf3ce44SJohn Forte 		ilu = stmf_state.stmf_ilulist;
611fcf3ce44SJohn Forte 		luid_list = (slist_lu_t *)obuf;
612fcf3ce44SJohn Forte 		for (i = 0; i < n; i++) {
613fcf3ce44SJohn Forte 			uint8_t *id;
614fcf3ce44SJohn Forte 			id = (uint8_t *)ilu->ilu_lu->lu_id;
615fcf3ce44SJohn Forte 			bcopy(id + 4, luid_list[i].lu_guid, 16);
616fcf3ce44SJohn Forte 			ilu = ilu->ilu_next;
617fcf3ce44SJohn Forte 		}
618fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
619fcf3ce44SJohn Forte 		break;
620fcf3ce44SJohn Forte 
6218fe96085Stim szeto 	case STMF_IOCTL_VE_LU_LIST:
6228fe96085Stim szeto 		mutex_enter(&stmf_state.stmf_lock);
6238fe96085Stim szeto 		id_list = &stmf_state.stmf_luid_list;
6248fe96085Stim szeto 		n = min(id_list->id_count,
6258fe96085Stim szeto 		    (iocd->stmf_obuf_size)/sizeof (slist_lu_t));
6268fe96085Stim szeto 		iocd->stmf_obuf_max_nentries = id_list->id_count;
6278fe96085Stim szeto 		iocd->stmf_obuf_nentries = n;
6288fe96085Stim szeto 		luid_list = (slist_lu_t *)obuf;
6298fe96085Stim szeto 		id_entry = id_list->idl_head;
6308fe96085Stim szeto 		for (i = 0; i < n; i++) {
6318fe96085Stim szeto 			bcopy(id_entry->id_data, luid_list[i].lu_guid, 16);
6328fe96085Stim szeto 			id_entry = id_entry->id_next;
6338fe96085Stim szeto 		}
6348fe96085Stim szeto 		mutex_exit(&stmf_state.stmf_lock);
6358fe96085Stim szeto 		break;
6368fe96085Stim szeto 
637fcf3ce44SJohn Forte 	case STMF_IOCTL_TARGET_PORT_LIST:
638fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
639fcf3ce44SJohn Forte 		iocd->stmf_obuf_max_nentries = stmf_state.stmf_nlports;
640fcf3ce44SJohn Forte 		n = min(stmf_state.stmf_nlports,
641fcf3ce44SJohn Forte 		    (iocd->stmf_obuf_size)/sizeof (slist_target_port_t));
642fcf3ce44SJohn Forte 		iocd->stmf_obuf_nentries = n;
643fcf3ce44SJohn Forte 		ilport = stmf_state.stmf_ilportlist;
644fcf3ce44SJohn Forte 		lportid_list = (slist_target_port_t *)obuf;
645fcf3ce44SJohn Forte 		for (i = 0; i < n; i++) {
646fcf3ce44SJohn Forte 			uint8_t *id;
647fcf3ce44SJohn Forte 			id = (uint8_t *)ilport->ilport_lport->lport_id;
648fcf3ce44SJohn Forte 			bcopy(id, lportid_list[i].target, id[3] + 4);
649fcf3ce44SJohn Forte 			ilport = ilport->ilport_next;
650fcf3ce44SJohn Forte 		}
651fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
652fcf3ce44SJohn Forte 		break;
653fcf3ce44SJohn Forte 
654fcf3ce44SJohn Forte 	case STMF_IOCTL_SESSION_LIST:
655fcf3ce44SJohn Forte 		p_id = (uint8_t *)ibuf;
656fcf3ce44SJohn Forte 		if ((p_id == NULL) || (iocd->stmf_ibuf_size < 4) ||
657fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < (p_id[3] + 4))) {
658fcf3ce44SJohn Forte 			ret = EINVAL;
659fcf3ce44SJohn Forte 			break;
660fcf3ce44SJohn Forte 		}
661fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
662fcf3ce44SJohn Forte 		for (ilport = stmf_state.stmf_ilportlist; ilport; ilport =
663fcf3ce44SJohn Forte 		    ilport->ilport_next) {
664fcf3ce44SJohn Forte 			uint8_t *id;
665fcf3ce44SJohn Forte 			id = (uint8_t *)ilport->ilport_lport->lport_id;
666fcf3ce44SJohn Forte 			if ((p_id[3] == id[3]) &&
667fcf3ce44SJohn Forte 			    (bcmp(p_id + 4, id + 4, id[3]) == 0)) {
668fcf3ce44SJohn Forte 				break;
669fcf3ce44SJohn Forte 			}
670fcf3ce44SJohn Forte 		}
671fcf3ce44SJohn Forte 		if (ilport == NULL) {
672fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
673fcf3ce44SJohn Forte 			ret = ENOENT;
674fcf3ce44SJohn Forte 			break;
675fcf3ce44SJohn Forte 		}
676fcf3ce44SJohn Forte 		iocd->stmf_obuf_max_nentries = ilport->ilport_nsessions;
677fcf3ce44SJohn Forte 		n = min(ilport->ilport_nsessions,
678fcf3ce44SJohn Forte 		    (iocd->stmf_obuf_size)/sizeof (slist_scsi_session_t));
679fcf3ce44SJohn Forte 		iocd->stmf_obuf_nentries = n;
680fcf3ce44SJohn Forte 		iss = ilport->ilport_ss_list;
681fcf3ce44SJohn Forte 		iss_list = (slist_scsi_session_t *)obuf;
682fcf3ce44SJohn Forte 		for (i = 0; i < n; i++) {
683fcf3ce44SJohn Forte 			uint8_t *id;
684fcf3ce44SJohn Forte 			id = (uint8_t *)iss->iss_ss->ss_rport_id;
685fcf3ce44SJohn Forte 			bcopy(id, iss_list[i].initiator, id[3] + 4);
686fcf3ce44SJohn Forte 			iss_list[i].creation_time = (uint32_t)
687fcf3ce44SJohn Forte 			    iss->iss_creation_time;
688fcf3ce44SJohn Forte 			if (iss->iss_ss->ss_rport_alias) {
689fcf3ce44SJohn Forte 				(void) strncpy(iss_list[i].alias,
690fcf3ce44SJohn Forte 				    iss->iss_ss->ss_rport_alias, 255);
691bad5e468SToomas Soome 				iss_list[i].alias[255] = '\0';
692fcf3ce44SJohn Forte 			} else {
693bad5e468SToomas Soome 				iss_list[i].alias[0] = '\0';
694fcf3ce44SJohn Forte 			}
695fcf3ce44SJohn Forte 			iss = iss->iss_next;
696fcf3ce44SJohn Forte 		}
697fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
698fcf3ce44SJohn Forte 		break;
699fcf3ce44SJohn Forte 
700fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_LU_PROPERTIES:
701fcf3ce44SJohn Forte 		p_id = (uint8_t *)ibuf;
702fcf3ce44SJohn Forte 		if ((iocd->stmf_ibuf_size < 16) ||
703fcf3ce44SJohn Forte 		    (iocd->stmf_obuf_size < sizeof (sioc_lu_props_t)) ||
704fcf3ce44SJohn Forte 		    (p_id[0] == 0)) {
705fcf3ce44SJohn Forte 			ret = EINVAL;
706fcf3ce44SJohn Forte 			break;
707fcf3ce44SJohn Forte 		}
708fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
709fcf3ce44SJohn Forte 		for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
710fcf3ce44SJohn Forte 			if (bcmp(p_id, ilu->ilu_lu->lu_id->ident, 16) == 0)
711fcf3ce44SJohn Forte 				break;
712fcf3ce44SJohn Forte 		}
713fcf3ce44SJohn Forte 		if (ilu == NULL) {
714fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
715fcf3ce44SJohn Forte 			ret = ENOENT;
716fcf3ce44SJohn Forte 			break;
717fcf3ce44SJohn Forte 		}
718fcf3ce44SJohn Forte 		lup = (sioc_lu_props_t *)obuf;
719fcf3ce44SJohn Forte 		bcopy(ilu->ilu_lu->lu_id->ident, lup->lu_guid, 16);
720fcf3ce44SJohn Forte 		lup->lu_state = ilu->ilu_state & 0x0f;
721fcf3ce44SJohn Forte 		lup->lu_present = 1; /* XXX */
722fcf3ce44SJohn Forte 		(void) strncpy(lup->lu_provider_name,
723fcf3ce44SJohn Forte 		    ilu->ilu_lu->lu_lp->lp_name, 255);
724bad5e468SToomas Soome 		lup->lu_provider_name[254] = '\0';
725fcf3ce44SJohn Forte 		if (ilu->ilu_lu->lu_alias) {
726fcf3ce44SJohn Forte 			(void) strncpy(lup->lu_alias,
727fcf3ce44SJohn Forte 			    ilu->ilu_lu->lu_alias, 255);
728bad5e468SToomas Soome 			lup->lu_alias[255] = '\0';
729fcf3ce44SJohn Forte 		} else {
730bad5e468SToomas Soome 			lup->lu_alias[0] = '\0';
731fcf3ce44SJohn Forte 		}
732fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
733fcf3ce44SJohn Forte 		break;
734fcf3ce44SJohn Forte 
735fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_TARGET_PORT_PROPERTIES:
736fcf3ce44SJohn Forte 		p_id = (uint8_t *)ibuf;
737fcf3ce44SJohn Forte 		if ((p_id == NULL) ||
738fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < (p_id[3] + 4)) ||
739fcf3ce44SJohn Forte 		    (iocd->stmf_obuf_size <
740fcf3ce44SJohn Forte 		    sizeof (sioc_target_port_props_t))) {
741fcf3ce44SJohn Forte 			ret = EINVAL;
742fcf3ce44SJohn Forte 			break;
743fcf3ce44SJohn Forte 		}
744fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
745fcf3ce44SJohn Forte 		for (ilport = stmf_state.stmf_ilportlist; ilport;
746fcf3ce44SJohn Forte 		    ilport = ilport->ilport_next) {
747fcf3ce44SJohn Forte 			uint8_t *id;
748fcf3ce44SJohn Forte 			id = (uint8_t *)ilport->ilport_lport->lport_id;
749fcf3ce44SJohn Forte 			if ((p_id[3] == id[3]) &&
750fcf3ce44SJohn Forte 			    (bcmp(p_id+4, id+4, id[3]) == 0))
751fcf3ce44SJohn Forte 				break;
752fcf3ce44SJohn Forte 		}
753fcf3ce44SJohn Forte 		if (ilport == NULL) {
754fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
755fcf3ce44SJohn Forte 			ret = ENOENT;
756fcf3ce44SJohn Forte 			break;
757fcf3ce44SJohn Forte 		}
758fcf3ce44SJohn Forte 		lportp = (sioc_target_port_props_t *)obuf;
759fcf3ce44SJohn Forte 		bcopy(ilport->ilport_lport->lport_id, lportp->tgt_id,
760fcf3ce44SJohn Forte 		    ilport->ilport_lport->lport_id->ident_length + 4);
761fcf3ce44SJohn Forte 		lportp->tgt_state = ilport->ilport_state & 0x0f;
762fcf3ce44SJohn Forte 		lportp->tgt_present = 1; /* XXX */
763fcf3ce44SJohn Forte 		(void) strncpy(lportp->tgt_provider_name,
764fcf3ce44SJohn Forte 		    ilport->ilport_lport->lport_pp->pp_name, 255);
765bad5e468SToomas Soome 		lportp->tgt_provider_name[254] = '\0';
766fcf3ce44SJohn Forte 		if (ilport->ilport_lport->lport_alias) {
767fcf3ce44SJohn Forte 			(void) strncpy(lportp->tgt_alias,
768fcf3ce44SJohn Forte 			    ilport->ilport_lport->lport_alias, 255);
769bad5e468SToomas Soome 			lportp->tgt_alias[255] = '\0';
770fcf3ce44SJohn Forte 		} else {
771bad5e468SToomas Soome 			lportp->tgt_alias[0] = '\0';
772fcf3ce44SJohn Forte 		}
773fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
774fcf3ce44SJohn Forte 		break;
775fcf3ce44SJohn Forte 
776fcf3ce44SJohn Forte 	case STMF_IOCTL_SET_STMF_STATE:
777fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
778fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
779fcf3ce44SJohn Forte 			ret = EINVAL;
780fcf3ce44SJohn Forte 			break;
781fcf3ce44SJohn Forte 		}
782fcf3ce44SJohn Forte 		ret = stmf_set_stmf_state((stmf_state_desc_t *)ibuf);
783fcf3ce44SJohn Forte 		break;
784fcf3ce44SJohn Forte 
785fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_STMF_STATE:
786fcf3ce44SJohn Forte 		if ((obuf == NULL) ||
787fcf3ce44SJohn Forte 		    (iocd->stmf_obuf_size < sizeof (stmf_state_desc_t))) {
788fcf3ce44SJohn Forte 			ret = EINVAL;
789fcf3ce44SJohn Forte 			break;
790fcf3ce44SJohn Forte 		}
791fcf3ce44SJohn Forte 		ret = stmf_get_stmf_state((stmf_state_desc_t *)obuf);
792fcf3ce44SJohn Forte 		break;
793fcf3ce44SJohn Forte 
79445039663SJohn Forte 	case STMF_IOCTL_SET_ALUA_STATE:
79545039663SJohn Forte 		if ((ibuf == NULL) ||
79645039663SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_alua_state_desc_t))) {
79745039663SJohn Forte 			ret = EINVAL;
79845039663SJohn Forte 			break;
79945039663SJohn Forte 		}
80045039663SJohn Forte 		ret = stmf_set_alua_state((stmf_alua_state_desc_t *)ibuf);
80145039663SJohn Forte 		break;
80245039663SJohn Forte 
80345039663SJohn Forte 	case STMF_IOCTL_GET_ALUA_STATE:
80445039663SJohn Forte 		if ((obuf == NULL) ||
80545039663SJohn Forte 		    (iocd->stmf_obuf_size < sizeof (stmf_alua_state_desc_t))) {
80645039663SJohn Forte 			ret = EINVAL;
80745039663SJohn Forte 			break;
80845039663SJohn Forte 		}
80945039663SJohn Forte 		stmf_get_alua_state((stmf_alua_state_desc_t *)obuf);
81045039663SJohn Forte 		break;
81145039663SJohn Forte 
812fcf3ce44SJohn Forte 	case STMF_IOCTL_SET_LU_STATE:
813fcf3ce44SJohn Forte 		ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
814fcf3ce44SJohn Forte 		ssi.st_additional_info = NULL;
815fcf3ce44SJohn Forte 		std = (stmf_state_desc_t *)ibuf;
816fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
817fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
818fcf3ce44SJohn Forte 			ret = EINVAL;
819fcf3ce44SJohn Forte 			break;
820fcf3ce44SJohn Forte 		}
821fcf3ce44SJohn Forte 		p_id = std->ident;
822fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
823fcf3ce44SJohn Forte 		if (stmf_state.stmf_inventory_locked) {
824fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
825fcf3ce44SJohn Forte 			ret = EBUSY;
826fcf3ce44SJohn Forte 			break;
827fcf3ce44SJohn Forte 		}
828fcf3ce44SJohn Forte 		for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
829fcf3ce44SJohn Forte 			if (bcmp(p_id, ilu->ilu_lu->lu_id->ident, 16) == 0)
830fcf3ce44SJohn Forte 				break;
831fcf3ce44SJohn Forte 		}
832fcf3ce44SJohn Forte 		if (ilu == NULL) {
833fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
834fcf3ce44SJohn Forte 			ret = ENOENT;
835fcf3ce44SJohn Forte 			break;
836fcf3ce44SJohn Forte 		}
837fcf3ce44SJohn Forte 		stmf_state.stmf_inventory_locked = 1;
838fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
839fcf3ce44SJohn Forte 		cmd = (std->state == STMF_STATE_ONLINE) ? STMF_CMD_LU_ONLINE :
840fcf3ce44SJohn Forte 		    STMF_CMD_LU_OFFLINE;
841fcf3ce44SJohn Forte 		ctl_ret = stmf_ctl(cmd, (void *)ilu->ilu_lu, &ssi);
842fcf3ce44SJohn Forte 		if (ctl_ret == STMF_ALREADY)
843fcf3ce44SJohn Forte 			ret = 0;
8444f486358SNattuvetty Bhavyan 		else if (ctl_ret == STMF_BUSY)
8454f486358SNattuvetty Bhavyan 			ret = EBUSY;
846fcf3ce44SJohn Forte 		else if (ctl_ret != STMF_SUCCESS)
847fcf3ce44SJohn Forte 			ret = EIO;
848fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
849fcf3ce44SJohn Forte 		stmf_state.stmf_inventory_locked = 0;
850fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
851fcf3ce44SJohn Forte 		break;
852fcf3ce44SJohn Forte 
8534b31676fSsrivijitha dugganapalli 	case STMF_IOCTL_SET_STMF_PROPS:
8544b31676fSsrivijitha dugganapalli 		if ((ibuf == NULL) ||
8554b31676fSsrivijitha dugganapalli 		    (iocd->stmf_ibuf_size < sizeof (stmf_set_props_t))) {
8564b31676fSsrivijitha dugganapalli 			ret = EINVAL;
8574b31676fSsrivijitha dugganapalli 			break;
8584b31676fSsrivijitha dugganapalli 		}
8594b31676fSsrivijitha dugganapalli 		stmf_set_props = (stmf_set_props_t *)ibuf;
8604b31676fSsrivijitha dugganapalli 		mutex_enter(&stmf_state.stmf_lock);
8614b31676fSsrivijitha dugganapalli 		if ((stmf_set_props->default_lu_state_value ==
8624b31676fSsrivijitha dugganapalli 		    STMF_STATE_OFFLINE) ||
8634b31676fSsrivijitha dugganapalli 		    (stmf_set_props->default_lu_state_value ==
8644b31676fSsrivijitha dugganapalli 		    STMF_STATE_ONLINE)) {
8654b31676fSsrivijitha dugganapalli 			stmf_state.stmf_default_lu_state =
8664b31676fSsrivijitha dugganapalli 			    stmf_set_props->default_lu_state_value;
8674b31676fSsrivijitha dugganapalli 		}
8684b31676fSsrivijitha dugganapalli 		if ((stmf_set_props->default_target_state_value ==
8694b31676fSsrivijitha dugganapalli 		    STMF_STATE_OFFLINE) ||
8704b31676fSsrivijitha dugganapalli 		    (stmf_set_props->default_target_state_value ==
8714b31676fSsrivijitha dugganapalli 		    STMF_STATE_ONLINE)) {
8724b31676fSsrivijitha dugganapalli 			stmf_state.stmf_default_lport_state =
8734b31676fSsrivijitha dugganapalli 			    stmf_set_props->default_target_state_value;
8744b31676fSsrivijitha dugganapalli 		}
8754b31676fSsrivijitha dugganapalli 
8764b31676fSsrivijitha dugganapalli 		mutex_exit(&stmf_state.stmf_lock);
8774b31676fSsrivijitha dugganapalli 		break;
8784b31676fSsrivijitha dugganapalli 
879fcf3ce44SJohn Forte 	case STMF_IOCTL_SET_TARGET_PORT_STATE:
880fcf3ce44SJohn Forte 		ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
881fcf3ce44SJohn Forte 		ssi.st_additional_info = NULL;
882fcf3ce44SJohn Forte 		std = (stmf_state_desc_t *)ibuf;
883fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
884fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
885fcf3ce44SJohn Forte 			ret = EINVAL;
886fcf3ce44SJohn Forte 			break;
887fcf3ce44SJohn Forte 		}
888fcf3ce44SJohn Forte 		p_id = std->ident;
889fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
890fcf3ce44SJohn Forte 		if (stmf_state.stmf_inventory_locked) {
891fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
892fcf3ce44SJohn Forte 			ret = EBUSY;
893fcf3ce44SJohn Forte 			break;
894fcf3ce44SJohn Forte 		}
895fcf3ce44SJohn Forte 		for (ilport = stmf_state.stmf_ilportlist; ilport;
896fcf3ce44SJohn Forte 		    ilport = ilport->ilport_next) {
897fcf3ce44SJohn Forte 			uint8_t *id;
898fcf3ce44SJohn Forte 			id = (uint8_t *)ilport->ilport_lport->lport_id;
899fcf3ce44SJohn Forte 			if ((id[3] == p_id[3]) &&
900fcf3ce44SJohn Forte 			    (bcmp(id+4, p_id+4, id[3]) == 0)) {
901fcf3ce44SJohn Forte 				break;
902fcf3ce44SJohn Forte 			}
903fcf3ce44SJohn Forte 		}
904fcf3ce44SJohn Forte 		if (ilport == NULL) {
905fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
906fcf3ce44SJohn Forte 			ret = ENOENT;
907fcf3ce44SJohn Forte 			break;
908fcf3ce44SJohn Forte 		}
909fcf3ce44SJohn Forte 		stmf_state.stmf_inventory_locked = 1;
910fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
911fcf3ce44SJohn Forte 		cmd = (std->state == STMF_STATE_ONLINE) ?
912fcf3ce44SJohn Forte 		    STMF_CMD_LPORT_ONLINE : STMF_CMD_LPORT_OFFLINE;
913fcf3ce44SJohn Forte 		ctl_ret = stmf_ctl(cmd, (void *)ilport->ilport_lport, &ssi);
914fcf3ce44SJohn Forte 		if (ctl_ret == STMF_ALREADY)
915fcf3ce44SJohn Forte 			ret = 0;
9164f486358SNattuvetty Bhavyan 		else if (ctl_ret == STMF_BUSY)
9174f486358SNattuvetty Bhavyan 			ret = EBUSY;
918fcf3ce44SJohn Forte 		else if (ctl_ret != STMF_SUCCESS)
919fcf3ce44SJohn Forte 			ret = EIO;
920fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
921fcf3ce44SJohn Forte 		stmf_state.stmf_inventory_locked = 0;
922fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
923fcf3ce44SJohn Forte 		break;
924fcf3ce44SJohn Forte 
925fcf3ce44SJohn Forte 	case STMF_IOCTL_ADD_HG_ENTRY:
926fcf3ce44SJohn Forte 		idtype = STMF_ID_TYPE_HOST;
927fcf3ce44SJohn Forte 		/* FALLTHROUGH */
928fcf3ce44SJohn Forte 	case STMF_IOCTL_ADD_TG_ENTRY:
929fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
930fcf3ce44SJohn Forte 			ret = EACCES;
931fcf3ce44SJohn Forte 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
932fcf3ce44SJohn Forte 			break;
933fcf3ce44SJohn Forte 		}
934fcf3ce44SJohn Forte 		if (cmd == STMF_IOCTL_ADD_TG_ENTRY) {
935fcf3ce44SJohn Forte 			idtype = STMF_ID_TYPE_TARGET;
936fcf3ce44SJohn Forte 		}
937fcf3ce44SJohn Forte 		grp_entry = (stmf_group_op_data_t *)ibuf;
938fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
939fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_op_data_t))) {
940fcf3ce44SJohn Forte 			ret = EINVAL;
941fcf3ce44SJohn Forte 			break;
942fcf3ce44SJohn Forte 		}
943fcf3ce44SJohn Forte 		if (grp_entry->group.name[0] == '*') {
944fcf3ce44SJohn Forte 			ret = EINVAL;
945fcf3ce44SJohn Forte 			break; /* not allowed */
946fcf3ce44SJohn Forte 		}
947fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
948fcf3ce44SJohn Forte 		ret = stmf_add_group_member(grp_entry->group.name,
949fcf3ce44SJohn Forte 		    grp_entry->group.name_size,
950fcf3ce44SJohn Forte 		    grp_entry->ident + 4,
951fcf3ce44SJohn Forte 		    grp_entry->ident[3],
952fcf3ce44SJohn Forte 		    idtype,
953fcf3ce44SJohn Forte 		    &iocd->stmf_error);
954fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
955fcf3ce44SJohn Forte 		break;
956fcf3ce44SJohn Forte 	case STMF_IOCTL_REMOVE_HG_ENTRY:
957fcf3ce44SJohn Forte 		idtype = STMF_ID_TYPE_HOST;
958fcf3ce44SJohn Forte 		/* FALLTHROUGH */
959fcf3ce44SJohn Forte 	case STMF_IOCTL_REMOVE_TG_ENTRY:
960fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
961fcf3ce44SJohn Forte 			ret = EACCES;
962fcf3ce44SJohn Forte 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
963fcf3ce44SJohn Forte 			break;
964fcf3ce44SJohn Forte 		}
965fcf3ce44SJohn Forte 		if (cmd == STMF_IOCTL_REMOVE_TG_ENTRY) {
966fcf3ce44SJohn Forte 			idtype = STMF_ID_TYPE_TARGET;
967fcf3ce44SJohn Forte 		}
968fcf3ce44SJohn Forte 		grp_entry = (stmf_group_op_data_t *)ibuf;
969fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
970fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_op_data_t))) {
971fcf3ce44SJohn Forte 			ret = EINVAL;
972fcf3ce44SJohn Forte 			break;
973fcf3ce44SJohn Forte 		}
974fcf3ce44SJohn Forte 		if (grp_entry->group.name[0] == '*') {
975fcf3ce44SJohn Forte 			ret = EINVAL;
976fcf3ce44SJohn Forte 			break; /* not allowed */
977fcf3ce44SJohn Forte 		}
978fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
979fcf3ce44SJohn Forte 		ret = stmf_remove_group_member(grp_entry->group.name,
980fcf3ce44SJohn Forte 		    grp_entry->group.name_size,
981fcf3ce44SJohn Forte 		    grp_entry->ident + 4,
982fcf3ce44SJohn Forte 		    grp_entry->ident[3],
983fcf3ce44SJohn Forte 		    idtype,
984fcf3ce44SJohn Forte 		    &iocd->stmf_error);
985fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
986fcf3ce44SJohn Forte 		break;
987fcf3ce44SJohn Forte 	case STMF_IOCTL_CREATE_HOST_GROUP:
988fcf3ce44SJohn Forte 		idtype = STMF_ID_TYPE_HOST_GROUP;
989fcf3ce44SJohn Forte 		/* FALLTHROUGH */
990fcf3ce44SJohn Forte 	case STMF_IOCTL_CREATE_TARGET_GROUP:
991fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
992fcf3ce44SJohn Forte 			ret = EACCES;
993fcf3ce44SJohn Forte 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
994fcf3ce44SJohn Forte 			break;
995fcf3ce44SJohn Forte 		}
996fcf3ce44SJohn Forte 		grpname = (stmf_group_name_t *)ibuf;
997fcf3ce44SJohn Forte 
998fcf3ce44SJohn Forte 		if (cmd == STMF_IOCTL_CREATE_TARGET_GROUP)
999fcf3ce44SJohn Forte 			idtype = STMF_ID_TYPE_TARGET_GROUP;
1000fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
1001fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
1002fcf3ce44SJohn Forte 			ret = EINVAL;
1003fcf3ce44SJohn Forte 			break;
1004fcf3ce44SJohn Forte 		}
1005fcf3ce44SJohn Forte 		if (grpname->name[0] == '*') {
1006fcf3ce44SJohn Forte 			ret = EINVAL;
1007fcf3ce44SJohn Forte 			break; /* not allowed */
1008fcf3ce44SJohn Forte 		}
1009fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
1010fcf3ce44SJohn Forte 		ret = stmf_add_group(grpname->name,
1011fcf3ce44SJohn Forte 		    grpname->name_size, idtype, &iocd->stmf_error);
1012fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1013fcf3ce44SJohn Forte 		break;
1014fcf3ce44SJohn Forte 	case STMF_IOCTL_REMOVE_HOST_GROUP:
1015fcf3ce44SJohn Forte 		idtype = STMF_ID_TYPE_HOST_GROUP;
1016fcf3ce44SJohn Forte 		/* FALLTHROUGH */
1017fcf3ce44SJohn Forte 	case STMF_IOCTL_REMOVE_TARGET_GROUP:
1018fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1019fcf3ce44SJohn Forte 			ret = EACCES;
1020fcf3ce44SJohn Forte 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1021fcf3ce44SJohn Forte 			break;
1022fcf3ce44SJohn Forte 		}
1023fcf3ce44SJohn Forte 		grpname = (stmf_group_name_t *)ibuf;
1024fcf3ce44SJohn Forte 		if (cmd == STMF_IOCTL_REMOVE_TARGET_GROUP)
1025fcf3ce44SJohn Forte 			idtype = STMF_ID_TYPE_TARGET_GROUP;
1026fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
1027fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
1028fcf3ce44SJohn Forte 			ret = EINVAL;
1029fcf3ce44SJohn Forte 			break;
1030fcf3ce44SJohn Forte 		}
1031fcf3ce44SJohn Forte 		if (grpname->name[0] == '*') {
1032fcf3ce44SJohn Forte 			ret = EINVAL;
1033fcf3ce44SJohn Forte 			break; /* not allowed */
1034fcf3ce44SJohn Forte 		}
1035fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
1036fcf3ce44SJohn Forte 		ret = stmf_remove_group(grpname->name,
1037fcf3ce44SJohn Forte 		    grpname->name_size, idtype, &iocd->stmf_error);
1038fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1039fcf3ce44SJohn Forte 		break;
104063ed874aStim szeto 	case STMF_IOCTL_VALIDATE_VIEW:
1041fcf3ce44SJohn Forte 	case STMF_IOCTL_ADD_VIEW_ENTRY:
1042fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1043fcf3ce44SJohn Forte 			ret = EACCES;
1044fcf3ce44SJohn Forte 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1045fcf3ce44SJohn Forte 			break;
1046fcf3ce44SJohn Forte 		}
1047fcf3ce44SJohn Forte 		ve = (stmf_view_op_entry_t *)ibuf;
1048fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
1049fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_view_op_entry_t))) {
1050fcf3ce44SJohn Forte 			ret = EINVAL;
1051fcf3ce44SJohn Forte 			break;
1052fcf3ce44SJohn Forte 		}
1053fcf3ce44SJohn Forte 		if (!ve->ve_lu_number_valid)
1054fcf3ce44SJohn Forte 			ve->ve_lu_nbr[2] = 0xFF;
1055fcf3ce44SJohn Forte 		if (ve->ve_all_hosts) {
1056fcf3ce44SJohn Forte 			ve->ve_host_group.name[0] = '*';
1057fcf3ce44SJohn Forte 			ve->ve_host_group.name_size = 1;
1058fcf3ce44SJohn Forte 		}
1059fcf3ce44SJohn Forte 		if (ve->ve_all_targets) {
1060fcf3ce44SJohn Forte 			ve->ve_target_group.name[0] = '*';
1061fcf3ce44SJohn Forte 			ve->ve_target_group.name_size = 1;
1062fcf3ce44SJohn Forte 		}
1063fcf3ce44SJohn Forte 		if (ve->ve_ndx_valid)
1064fcf3ce44SJohn Forte 			veid = ve->ve_ndx;
1065fcf3ce44SJohn Forte 		else
1066fcf3ce44SJohn Forte 			veid = 0xffffffff;
1067fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
106863ed874aStim szeto 		if (cmd == STMF_IOCTL_ADD_VIEW_ENTRY) {
1069fcf3ce44SJohn Forte 			ret = stmf_add_ve(ve->ve_host_group.name,
1070fcf3ce44SJohn Forte 			    ve->ve_host_group.name_size,
1071fcf3ce44SJohn Forte 			    ve->ve_target_group.name,
1072fcf3ce44SJohn Forte 			    ve->ve_target_group.name_size,
1073fcf3ce44SJohn Forte 			    ve->ve_guid,
1074fcf3ce44SJohn Forte 			    &veid,
1075fcf3ce44SJohn Forte 			    ve->ve_lu_nbr,
1076fcf3ce44SJohn Forte 			    &iocd->stmf_error);
107763ed874aStim szeto 		} else {  /* STMF_IOCTL_VALIDATE_VIEW */
107863ed874aStim szeto 			ret = stmf_validate_lun_ve(ve->ve_host_group.name,
107963ed874aStim szeto 			    ve->ve_host_group.name_size,
108063ed874aStim szeto 			    ve->ve_target_group.name,
108163ed874aStim szeto 			    ve->ve_target_group.name_size,
108263ed874aStim szeto 			    ve->ve_lu_nbr,
108363ed874aStim szeto 			    &iocd->stmf_error);
108463ed874aStim szeto 		}
1085fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1086fcf3ce44SJohn Forte 		if (ret == 0 &&
1087fcf3ce44SJohn Forte 		    (!ve->ve_ndx_valid || !ve->ve_lu_number_valid) &&
1088fcf3ce44SJohn Forte 		    iocd->stmf_obuf_size >= sizeof (stmf_view_op_entry_t)) {
1089fcf3ce44SJohn Forte 			stmf_view_op_entry_t *ve_ret =
1090fcf3ce44SJohn Forte 			    (stmf_view_op_entry_t *)obuf;
1091fcf3ce44SJohn Forte 			iocd->stmf_obuf_nentries = 1;
1092fcf3ce44SJohn Forte 			iocd->stmf_obuf_max_nentries = 1;
1093fcf3ce44SJohn Forte 			if (!ve->ve_ndx_valid) {
1094fcf3ce44SJohn Forte 				ve_ret->ve_ndx = veid;
1095fcf3ce44SJohn Forte 				ve_ret->ve_ndx_valid = 1;
1096fcf3ce44SJohn Forte 			}
1097fcf3ce44SJohn Forte 			if (!ve->ve_lu_number_valid) {
1098fcf3ce44SJohn Forte 				ve_ret->ve_lu_number_valid = 1;
1099fcf3ce44SJohn Forte 				bcopy(ve->ve_lu_nbr, ve_ret->ve_lu_nbr, 8);
1100fcf3ce44SJohn Forte 			}
1101fcf3ce44SJohn Forte 		}
1102fcf3ce44SJohn Forte 		break;
1103fcf3ce44SJohn Forte 	case STMF_IOCTL_REMOVE_VIEW_ENTRY:
1104fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1105fcf3ce44SJohn Forte 			ret = EACCES;
1106fcf3ce44SJohn Forte 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1107fcf3ce44SJohn Forte 			break;
1108fcf3ce44SJohn Forte 		}
1109fcf3ce44SJohn Forte 		ve = (stmf_view_op_entry_t *)ibuf;
1110fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
1111fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_view_op_entry_t))) {
1112fcf3ce44SJohn Forte 			ret = EINVAL;
1113fcf3ce44SJohn Forte 			break;
1114fcf3ce44SJohn Forte 		}
1115fcf3ce44SJohn Forte 		if (!ve->ve_ndx_valid) {
1116fcf3ce44SJohn Forte 			ret = EINVAL;
1117fcf3ce44SJohn Forte 			break;
1118fcf3ce44SJohn Forte 		}
1119fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
1120fcf3ce44SJohn Forte 		ret = stmf_remove_ve_by_id(ve->ve_guid, ve->ve_ndx,
1121fcf3ce44SJohn Forte 		    &iocd->stmf_error);
1122fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1123fcf3ce44SJohn Forte 		break;
1124fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_HG_LIST:
1125fcf3ce44SJohn Forte 		id_list = &stmf_state.stmf_hg_list;
1126fcf3ce44SJohn Forte 		/* FALLTHROUGH */
1127fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_TG_LIST:
1128fcf3ce44SJohn Forte 		if (cmd == STMF_IOCTL_GET_TG_LIST)
1129fcf3ce44SJohn Forte 			id_list = &stmf_state.stmf_tg_list;
1130fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
1131fcf3ce44SJohn Forte 		iocd->stmf_obuf_max_nentries = id_list->id_count;
1132fcf3ce44SJohn Forte 		n = min(id_list->id_count,
1133fcf3ce44SJohn Forte 		    (iocd->stmf_obuf_size)/sizeof (stmf_group_name_t));
1134fcf3ce44SJohn Forte 		iocd->stmf_obuf_nentries = n;
1135fcf3ce44SJohn Forte 		id_entry = id_list->idl_head;
1136fcf3ce44SJohn Forte 		grpname = (stmf_group_name_t *)obuf;
1137fcf3ce44SJohn Forte 		for (i = 0; i < n; i++) {
11388fe96085Stim szeto 			if (id_entry->id_data[0] == '*') {
11398fe96085Stim szeto 				if (iocd->stmf_obuf_nentries > 0) {
11408fe96085Stim szeto 					iocd->stmf_obuf_nentries--;
11418fe96085Stim szeto 				}
11428fe96085Stim szeto 				id_entry = id_entry->id_next;
11438fe96085Stim szeto 				continue;
11448fe96085Stim szeto 			}
11458fe96085Stim szeto 			grpname->name_size = id_entry->id_data_size;
11468fe96085Stim szeto 			bcopy(id_entry->id_data, grpname->name,
1147fcf3ce44SJohn Forte 			    id_entry->id_data_size);
11488fe96085Stim szeto 			grpname++;
1149fcf3ce44SJohn Forte 			id_entry = id_entry->id_next;
1150fcf3ce44SJohn Forte 		}
1151fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1152fcf3ce44SJohn Forte 		break;
1153fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_HG_ENTRIES:
1154fcf3ce44SJohn Forte 		id_list = &stmf_state.stmf_hg_list;
1155fcf3ce44SJohn Forte 		/* FALLTHROUGH */
1156fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_TG_ENTRIES:
1157fcf3ce44SJohn Forte 		grpname = (stmf_group_name_t *)ibuf;
1158fcf3ce44SJohn Forte 		if ((ibuf == NULL) ||
1159fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
1160fcf3ce44SJohn Forte 			ret = EINVAL;
1161fcf3ce44SJohn Forte 			break;
1162fcf3ce44SJohn Forte 		}
1163fcf3ce44SJohn Forte 		if (cmd == STMF_IOCTL_GET_TG_ENTRIES) {
1164fcf3ce44SJohn Forte 			id_list = &stmf_state.stmf_tg_list;
1165fcf3ce44SJohn Forte 		}
1166fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
1167fcf3ce44SJohn Forte 		id_entry = stmf_lookup_id(id_list, grpname->name_size,
1168fcf3ce44SJohn Forte 		    grpname->name);
1169fcf3ce44SJohn Forte 		if (!id_entry)
1170fcf3ce44SJohn Forte 			ret = ENODEV;
1171fcf3ce44SJohn Forte 		else {
1172fcf3ce44SJohn Forte 			stmf_ge_ident_t *grp_entry;
1173fcf3ce44SJohn Forte 			id_list = (stmf_id_list_t *)id_entry->id_impl_specific;
1174fcf3ce44SJohn Forte 			iocd->stmf_obuf_max_nentries = id_list->id_count;
1175fcf3ce44SJohn Forte 			n = min(id_list->id_count,
1176fcf3ce44SJohn Forte 			    iocd->stmf_obuf_size/sizeof (stmf_ge_ident_t));
1177fcf3ce44SJohn Forte 			iocd->stmf_obuf_nentries = n;
1178fcf3ce44SJohn Forte 			id_entry = id_list->idl_head;
1179fcf3ce44SJohn Forte 			grp_entry = (stmf_ge_ident_t *)obuf;
1180fcf3ce44SJohn Forte 			for (i = 0; i < n; i++) {
11818fe96085Stim szeto 				bcopy(id_entry->id_data, grp_entry->ident,
1182fcf3ce44SJohn Forte 				    id_entry->id_data_size);
11838fe96085Stim szeto 				grp_entry->ident_size = id_entry->id_data_size;
1184fcf3ce44SJohn Forte 				id_entry = id_entry->id_next;
11858fe96085Stim szeto 				grp_entry++;
1186fcf3ce44SJohn Forte 			}
1187fcf3ce44SJohn Forte 		}
1188fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1189fcf3ce44SJohn Forte 		break;
11908fe96085Stim szeto 
1191fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_VE_LIST:
1192fcf3ce44SJohn Forte 		n = iocd->stmf_obuf_size/sizeof (stmf_view_op_entry_t);
1193fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
1194fcf3ce44SJohn Forte 		ve = (stmf_view_op_entry_t *)obuf;
11958fe96085Stim szeto 		for (id_entry = stmf_state.stmf_luid_list.idl_head;
11968fe96085Stim szeto 		    id_entry; id_entry = id_entry->id_next) {
11978fe96085Stim szeto 			for (view_entry = (stmf_view_entry_t *)
11988fe96085Stim szeto 			    id_entry->id_impl_specific; view_entry;
11998fe96085Stim szeto 			    view_entry = view_entry->ve_next) {
12008fe96085Stim szeto 				iocd->stmf_obuf_max_nentries++;
12018fe96085Stim szeto 				if (iocd->stmf_obuf_nentries >= n)
12028fe96085Stim szeto 					continue;
1203fcf3ce44SJohn Forte 				ve->ve_ndx_valid = 1;
1204fcf3ce44SJohn Forte 				ve->ve_ndx = view_entry->ve_id;
1205fcf3ce44SJohn Forte 				ve->ve_lu_number_valid = 1;
1206fcf3ce44SJohn Forte 				bcopy(view_entry->ve_lun, ve->ve_lu_nbr, 8);
1207fcf3ce44SJohn Forte 				bcopy(view_entry->ve_luid->id_data, ve->ve_guid,
1208fcf3ce44SJohn Forte 				    view_entry->ve_luid->id_data_size);
12098fe96085Stim szeto 				if (view_entry->ve_hg->id_data[0] == '*') {
1210fcf3ce44SJohn Forte 					ve->ve_all_hosts = 1;
12118fe96085Stim szeto 				} else {
1212fcf3ce44SJohn Forte 					bcopy(view_entry->ve_hg->id_data,
1213fcf3ce44SJohn Forte 					    ve->ve_host_group.name,
1214fcf3ce44SJohn Forte 					    view_entry->ve_hg->id_data_size);
12158fe96085Stim szeto 					ve->ve_host_group.name_size =
12168fe96085Stim szeto 					    view_entry->ve_hg->id_data_size;
12178fe96085Stim szeto 				}
12188fe96085Stim szeto 
12198fe96085Stim szeto 				if (view_entry->ve_tg->id_data[0] == '*') {
1220fcf3ce44SJohn Forte 					ve->ve_all_targets = 1;
12218fe96085Stim szeto 				} else {
1222fcf3ce44SJohn Forte 					bcopy(view_entry->ve_tg->id_data,
1223fcf3ce44SJohn Forte 					    ve->ve_target_group.name,
1224fcf3ce44SJohn Forte 					    view_entry->ve_tg->id_data_size);
12258fe96085Stim szeto 					ve->ve_target_group.name_size =
12268fe96085Stim szeto 					    view_entry->ve_tg->id_data_size;
12278fe96085Stim szeto 				}
12288fe96085Stim szeto 				ve++;
1229fcf3ce44SJohn Forte 				iocd->stmf_obuf_nentries++;
12308fe96085Stim szeto 			}
12318fe96085Stim szeto 		}
12328fe96085Stim szeto 		mutex_exit(&stmf_state.stmf_lock);
12338fe96085Stim szeto 		break;
12348fe96085Stim szeto 
12358fe96085Stim szeto 	case STMF_IOCTL_LU_VE_LIST:
12368fe96085Stim szeto 		p_id = (uint8_t *)ibuf;
12378fe96085Stim szeto 		if ((iocd->stmf_ibuf_size != 16) ||
12388fe96085Stim szeto 		    (iocd->stmf_obuf_size < sizeof (stmf_view_op_entry_t))) {
12398fe96085Stim szeto 			ret = EINVAL;
1240fcf3ce44SJohn Forte 			break;
1241fcf3ce44SJohn Forte 		}
12428fe96085Stim szeto 
12438fe96085Stim szeto 		n = iocd->stmf_obuf_size/sizeof (stmf_view_op_entry_t);
12448fe96085Stim szeto 		mutex_enter(&stmf_state.stmf_lock);
12458fe96085Stim szeto 		ve = (stmf_view_op_entry_t *)obuf;
12468fe96085Stim szeto 		for (id_entry = stmf_state.stmf_luid_list.idl_head;
12478fe96085Stim szeto 		    id_entry; id_entry = id_entry->id_next) {
12488fe96085Stim szeto 			if (bcmp(id_entry->id_data, p_id, 16) != 0)
12498fe96085Stim szeto 				continue;
12508fe96085Stim szeto 			for (view_entry = (stmf_view_entry_t *)
12518fe96085Stim szeto 			    id_entry->id_impl_specific; view_entry;
12528fe96085Stim szeto 			    view_entry = view_entry->ve_next) {
12538fe96085Stim szeto 				iocd->stmf_obuf_max_nentries++;
1254fcf3ce44SJohn Forte 				if (iocd->stmf_obuf_nentries >= n)
12558fe96085Stim szeto 					continue;
12568fe96085Stim szeto 				ve->ve_ndx_valid = 1;
12578fe96085Stim szeto 				ve->ve_ndx = view_entry->ve_id;
12588fe96085Stim szeto 				ve->ve_lu_number_valid = 1;
12598fe96085Stim szeto 				bcopy(view_entry->ve_lun, ve->ve_lu_nbr, 8);
12608fe96085Stim szeto 				bcopy(view_entry->ve_luid->id_data, ve->ve_guid,
12618fe96085Stim szeto 				    view_entry->ve_luid->id_data_size);
12628fe96085Stim szeto 				if (view_entry->ve_hg->id_data[0] == '*') {
12638fe96085Stim szeto 					ve->ve_all_hosts = 1;
12648fe96085Stim szeto 				} else {
12658fe96085Stim szeto 					bcopy(view_entry->ve_hg->id_data,
12668fe96085Stim szeto 					    ve->ve_host_group.name,
12678fe96085Stim szeto 					    view_entry->ve_hg->id_data_size);
12688fe96085Stim szeto 					ve->ve_host_group.name_size =
12698fe96085Stim szeto 					    view_entry->ve_hg->id_data_size;
12708fe96085Stim szeto 				}
12718fe96085Stim szeto 
12728fe96085Stim szeto 				if (view_entry->ve_tg->id_data[0] == '*') {
12738fe96085Stim szeto 					ve->ve_all_targets = 1;
12748fe96085Stim szeto 				} else {
12758fe96085Stim szeto 					bcopy(view_entry->ve_tg->id_data,
12768fe96085Stim szeto 					    ve->ve_target_group.name,
12778fe96085Stim szeto 					    view_entry->ve_tg->id_data_size);
12788fe96085Stim szeto 					ve->ve_target_group.name_size =
12798fe96085Stim szeto 					    view_entry->ve_tg->id_data_size;
12808fe96085Stim szeto 				}
12818fe96085Stim szeto 				ve++;
12828fe96085Stim szeto 				iocd->stmf_obuf_nentries++;
12838fe96085Stim szeto 			}
1284fcf3ce44SJohn Forte 			break;
1285fcf3ce44SJohn Forte 		}
1286fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1287fcf3ce44SJohn Forte 		break;
12888fe96085Stim szeto 
1289fcf3ce44SJohn Forte 	case STMF_IOCTL_LOAD_PP_DATA:
1290fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1291fcf3ce44SJohn Forte 			ret = EACCES;
1292fcf3ce44SJohn Forte 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1293fcf3ce44SJohn Forte 			break;
1294fcf3ce44SJohn Forte 		}
1295fcf3ce44SJohn Forte 		ppi = (stmf_ppioctl_data_t *)ibuf;
1296fcf3ce44SJohn Forte 		if ((ppi == NULL) ||
1297fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
1298fcf3ce44SJohn Forte 			ret = EINVAL;
1299fcf3ce44SJohn Forte 			break;
1300fcf3ce44SJohn Forte 		}
13018fe96085Stim szeto 		/* returned token */
13028fe96085Stim szeto 		ppi_token = (uint64_t *)obuf;
13038fe96085Stim szeto 		if ((ppi_token == NULL) ||
13048fe96085Stim szeto 		    (iocd->stmf_obuf_size < sizeof (uint64_t))) {
13058fe96085Stim szeto 			ret = EINVAL;
13068fe96085Stim szeto 			break;
13078fe96085Stim szeto 		}
13088fe96085Stim szeto 		ret = stmf_load_ppd_ioctl(ppi, ppi_token, &iocd->stmf_error);
13098fe96085Stim szeto 		break;
13108fe96085Stim szeto 
13118fe96085Stim szeto 	case STMF_IOCTL_GET_PP_DATA:
13128fe96085Stim szeto 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
13138fe96085Stim szeto 			ret = EACCES;
13148fe96085Stim szeto 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
13158fe96085Stim szeto 			break;
13168fe96085Stim szeto 		}
13178fe96085Stim szeto 		ppi = (stmf_ppioctl_data_t *)ibuf;
13188fe96085Stim szeto 		if (ppi == NULL ||
13198fe96085Stim szeto 		    (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
13208fe96085Stim szeto 			ret = EINVAL;
13218fe96085Stim szeto 			break;
13228fe96085Stim szeto 		}
13238fe96085Stim szeto 		ppi_out = (stmf_ppioctl_data_t *)obuf;
13248fe96085Stim szeto 		if ((ppi_out == NULL) ||
13258fe96085Stim szeto 		    (iocd->stmf_obuf_size < sizeof (stmf_ppioctl_data_t))) {
13268fe96085Stim szeto 			ret = EINVAL;
13278fe96085Stim szeto 			break;
13288fe96085Stim szeto 		}
13298fe96085Stim szeto 		ret = stmf_get_ppd_ioctl(ppi, ppi_out, &iocd->stmf_error);
1330fcf3ce44SJohn Forte 		break;
1331fcf3ce44SJohn Forte 
1332fcf3ce44SJohn Forte 	case STMF_IOCTL_CLEAR_PP_DATA:
1333fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1334fcf3ce44SJohn Forte 			ret = EACCES;
1335fcf3ce44SJohn Forte 			iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1336fcf3ce44SJohn Forte 			break;
1337fcf3ce44SJohn Forte 		}
1338fcf3ce44SJohn Forte 		ppi = (stmf_ppioctl_data_t *)ibuf;
1339fcf3ce44SJohn Forte 		if ((ppi == NULL) ||
1340fcf3ce44SJohn Forte 		    (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
1341fcf3ce44SJohn Forte 			ret = EINVAL;
1342fcf3ce44SJohn Forte 			break;
1343fcf3ce44SJohn Forte 		}
1344fcf3ce44SJohn Forte 		ret = stmf_delete_ppd_ioctl(ppi);
1345fcf3ce44SJohn Forte 		break;
1346fcf3ce44SJohn Forte 
1347fcf3ce44SJohn Forte 	case STMF_IOCTL_CLEAR_TRACE:
1348fcf3ce44SJohn Forte 		stmf_trace_clear();
1349fcf3ce44SJohn Forte 		break;
1350fcf3ce44SJohn Forte 
1351fcf3ce44SJohn Forte 	case STMF_IOCTL_ADD_TRACE:
1352fcf3ce44SJohn Forte 		if (iocd->stmf_ibuf_size && ibuf) {
1353bad5e468SToomas Soome 			((uint8_t *)ibuf)[iocd->stmf_ibuf_size - 1] = '\0';
1354fcf3ce44SJohn Forte 			stmf_trace("\nstradm", "%s\n", ibuf);
1355fcf3ce44SJohn Forte 		}
1356fcf3ce44SJohn Forte 		break;
1357fcf3ce44SJohn Forte 
1358fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_TRACE_POSITION:
1359fcf3ce44SJohn Forte 		if (obuf && (iocd->stmf_obuf_size > 3)) {
1360fcf3ce44SJohn Forte 			mutex_enter(&trace_buf_lock);
1361fcf3ce44SJohn Forte 			*((int *)obuf) = trace_buf_curndx;
1362fcf3ce44SJohn Forte 			mutex_exit(&trace_buf_lock);
1363fcf3ce44SJohn Forte 		} else {
1364fcf3ce44SJohn Forte 			ret = EINVAL;
1365fcf3ce44SJohn Forte 		}
1366fcf3ce44SJohn Forte 		break;
1367fcf3ce44SJohn Forte 
1368fcf3ce44SJohn Forte 	case STMF_IOCTL_GET_TRACE:
1369fcf3ce44SJohn Forte 		if ((iocd->stmf_obuf_size == 0) || (iocd->stmf_ibuf_size < 4)) {
1370fcf3ce44SJohn Forte 			ret = EINVAL;
1371fcf3ce44SJohn Forte 			break;
1372fcf3ce44SJohn Forte 		}
1373fcf3ce44SJohn Forte 		i = *((int *)ibuf);
1374fcf3ce44SJohn Forte 		if ((i > trace_buf_size) || ((i + iocd->stmf_obuf_size) >
1375fcf3ce44SJohn Forte 		    trace_buf_size)) {
1376fcf3ce44SJohn Forte 			ret = EINVAL;
1377fcf3ce44SJohn Forte 			break;
1378fcf3ce44SJohn Forte 		}
1379fcf3ce44SJohn Forte 		mutex_enter(&trace_buf_lock);
1380fcf3ce44SJohn Forte 		bcopy(stmf_trace_buf + i, obuf, iocd->stmf_obuf_size);
1381fcf3ce44SJohn Forte 		mutex_exit(&trace_buf_lock);
1382fcf3ce44SJohn Forte 		break;
1383fcf3ce44SJohn Forte 
1384fcf3ce44SJohn Forte 	default:
1385fcf3ce44SJohn Forte 		ret = ENOTTY;
1386fcf3ce44SJohn Forte 	}
1387fcf3ce44SJohn Forte 
1388fcf3ce44SJohn Forte 	if (ret == 0) {
1389fcf3ce44SJohn Forte 		ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
1390fcf3ce44SJohn Forte 	} else if (iocd->stmf_error) {
1391fcf3ce44SJohn Forte 		(void) stmf_copyout_iocdata(data, mode, iocd, obuf);
1392fcf3ce44SJohn Forte 	}
1393fcf3ce44SJohn Forte 	if (obuf) {
1394fcf3ce44SJohn Forte 		kmem_free(obuf, iocd->stmf_obuf_size);
1395fcf3ce44SJohn Forte 		obuf = NULL;
1396fcf3ce44SJohn Forte 	}
1397fcf3ce44SJohn Forte 	if (ibuf) {
1398fcf3ce44SJohn Forte 		kmem_free(ibuf, iocd->stmf_ibuf_size);
1399fcf3ce44SJohn Forte 		ibuf = NULL;
1400fcf3ce44SJohn Forte 	}
1401fcf3ce44SJohn Forte 	kmem_free(iocd, sizeof (stmf_iocdata_t));
1402fcf3ce44SJohn Forte 	return (ret);
1403fcf3ce44SJohn Forte }
1404fcf3ce44SJohn Forte 
1405fcf3ce44SJohn Forte static int
stmf_get_service_state()1406fcf3ce44SJohn Forte stmf_get_service_state()
1407fcf3ce44SJohn Forte {
1408fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
1409fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
1410fcf3ce44SJohn Forte 	int online = 0;
1411fcf3ce44SJohn Forte 	int offline = 0;
1412fcf3ce44SJohn Forte 	int onlining = 0;
1413fcf3ce44SJohn Forte 	int offlining = 0;
1414fcf3ce44SJohn Forte 
1415fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1416fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1417fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
1418fcf3ce44SJohn Forte 		if (ilport->ilport_state == STMF_STATE_OFFLINE)
1419fcf3ce44SJohn Forte 			offline++;
1420fcf3ce44SJohn Forte 		else if (ilport->ilport_state == STMF_STATE_ONLINE)
1421fcf3ce44SJohn Forte 			online++;
1422fcf3ce44SJohn Forte 		else if (ilport->ilport_state == STMF_STATE_ONLINING)
1423fcf3ce44SJohn Forte 			onlining++;
1424fcf3ce44SJohn Forte 		else if (ilport->ilport_state == STMF_STATE_OFFLINING)
1425fcf3ce44SJohn Forte 			offlining++;
1426fcf3ce44SJohn Forte 	}
1427fcf3ce44SJohn Forte 
1428fcf3ce44SJohn Forte 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
1429fcf3ce44SJohn Forte 	    ilu = ilu->ilu_next) {
1430fcf3ce44SJohn Forte 		if (ilu->ilu_state == STMF_STATE_OFFLINE)
1431fcf3ce44SJohn Forte 			offline++;
1432fcf3ce44SJohn Forte 		else if (ilu->ilu_state == STMF_STATE_ONLINE)
1433fcf3ce44SJohn Forte 			online++;
1434fcf3ce44SJohn Forte 		else if (ilu->ilu_state == STMF_STATE_ONLINING)
1435fcf3ce44SJohn Forte 			onlining++;
1436fcf3ce44SJohn Forte 		else if (ilu->ilu_state == STMF_STATE_OFFLINING)
1437fcf3ce44SJohn Forte 			offlining++;
1438fcf3ce44SJohn Forte 	}
1439fcf3ce44SJohn Forte 
1440fcf3ce44SJohn Forte 	if (stmf_state.stmf_service_running) {
1441fcf3ce44SJohn Forte 		if (onlining)
1442fcf3ce44SJohn Forte 			return (STMF_STATE_ONLINING);
1443fcf3ce44SJohn Forte 		else
1444fcf3ce44SJohn Forte 			return (STMF_STATE_ONLINE);
1445fcf3ce44SJohn Forte 	}
1446fcf3ce44SJohn Forte 
1447fcf3ce44SJohn Forte 	if (offlining) {
1448fcf3ce44SJohn Forte 		return (STMF_STATE_OFFLINING);
1449fcf3ce44SJohn Forte 	}
1450fcf3ce44SJohn Forte 
1451fcf3ce44SJohn Forte 	return (STMF_STATE_OFFLINE);
1452fcf3ce44SJohn Forte }
1453fcf3ce44SJohn Forte 
1454fcf3ce44SJohn Forte static int
stmf_set_stmf_state(stmf_state_desc_t * std)1455fcf3ce44SJohn Forte stmf_set_stmf_state(stmf_state_desc_t *std)
1456fcf3ce44SJohn Forte {
1457fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
1458fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
1459fcf3ce44SJohn Forte 	stmf_state_change_info_t ssi;
1460fcf3ce44SJohn Forte 	int svc_state;
1461fcf3ce44SJohn Forte 
1462fcf3ce44SJohn Forte 	ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
1463fcf3ce44SJohn Forte 	ssi.st_additional_info = NULL;
1464fcf3ce44SJohn Forte 
1465fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
1466fcf3ce44SJohn Forte 	if (!stmf_state.stmf_exclusive_open) {
1467fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1468fcf3ce44SJohn Forte 		return (EACCES);
1469fcf3ce44SJohn Forte 	}
1470fcf3ce44SJohn Forte 
1471fcf3ce44SJohn Forte 	if (stmf_state.stmf_inventory_locked) {
1472fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1473fcf3ce44SJohn Forte 		return (EBUSY);
1474fcf3ce44SJohn Forte 	}
1475fcf3ce44SJohn Forte 
1476fcf3ce44SJohn Forte 	if ((std->state != STMF_STATE_ONLINE) &&
1477fcf3ce44SJohn Forte 	    (std->state != STMF_STATE_OFFLINE)) {
1478fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1479fcf3ce44SJohn Forte 		return (EINVAL);
1480fcf3ce44SJohn Forte 	}
1481fcf3ce44SJohn Forte 
1482fcf3ce44SJohn Forte 	svc_state = stmf_get_service_state();
1483fcf3ce44SJohn Forte 	if ((svc_state == STMF_STATE_OFFLINING) ||
1484fcf3ce44SJohn Forte 	    (svc_state == STMF_STATE_ONLINING)) {
1485fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1486fcf3ce44SJohn Forte 		return (EBUSY);
1487fcf3ce44SJohn Forte 	}
1488fcf3ce44SJohn Forte 
1489fcf3ce44SJohn Forte 	if (svc_state == STMF_STATE_OFFLINE) {
1490fcf3ce44SJohn Forte 		if (std->config_state == STMF_CONFIG_INIT) {
1491fcf3ce44SJohn Forte 			if (std->state != STMF_STATE_OFFLINE) {
1492fcf3ce44SJohn Forte 				mutex_exit(&stmf_state.stmf_lock);
1493fcf3ce44SJohn Forte 				return (EINVAL);
1494fcf3ce44SJohn Forte 			}
1495fcf3ce44SJohn Forte 			stmf_state.stmf_config_state = STMF_CONFIG_INIT;
1496fcf3ce44SJohn Forte 			stmf_delete_all_ppds();
1497fcf3ce44SJohn Forte 			stmf_view_clear_config();
1498fcf3ce44SJohn Forte 			stmf_view_init();
1499fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
1500fcf3ce44SJohn Forte 			return (0);
1501fcf3ce44SJohn Forte 		}
15025dfbf9beSSue Gleeson 		if ((stmf_state.stmf_config_state == STMF_CONFIG_INIT) ||
15035dfbf9beSSue Gleeson 		    (stmf_state.stmf_config_state == STMF_CONFIG_NONE)) {
1504fcf3ce44SJohn Forte 			if (std->config_state != STMF_CONFIG_INIT_DONE) {
1505fcf3ce44SJohn Forte 				mutex_exit(&stmf_state.stmf_lock);
1506fcf3ce44SJohn Forte 				return (EINVAL);
1507fcf3ce44SJohn Forte 			}
1508fcf3ce44SJohn Forte 			stmf_state.stmf_config_state = STMF_CONFIG_INIT_DONE;
1509fcf3ce44SJohn Forte 		}
1510fcf3ce44SJohn Forte 		if (std->state == STMF_STATE_OFFLINE) {
1511fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
1512fcf3ce44SJohn Forte 			return (0);
1513fcf3ce44SJohn Forte 		}
1514fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_INIT) {
1515fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
1516fcf3ce44SJohn Forte 			return (EINVAL);
1517fcf3ce44SJohn Forte 		}
1518fcf3ce44SJohn Forte 		stmf_state.stmf_inventory_locked = 1;
1519fcf3ce44SJohn Forte 		stmf_state.stmf_service_running = 1;
1520fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1521fcf3ce44SJohn Forte 
1522fcf3ce44SJohn Forte 		for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1523fcf3ce44SJohn Forte 		    ilport = ilport->ilport_next) {
15244b31676fSsrivijitha dugganapalli 			if (stmf_state.stmf_default_lport_state !=
15254b31676fSsrivijitha dugganapalli 			    STMF_STATE_ONLINE)
1526fcf3ce44SJohn Forte 				continue;
1527fcf3ce44SJohn Forte 			(void) stmf_ctl(STMF_CMD_LPORT_ONLINE,
1528fcf3ce44SJohn Forte 			    ilport->ilport_lport, &ssi);
1529fcf3ce44SJohn Forte 		}
1530fcf3ce44SJohn Forte 
1531fcf3ce44SJohn Forte 		for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
1532fcf3ce44SJohn Forte 		    ilu = ilu->ilu_next) {
15334b31676fSsrivijitha dugganapalli 			if (stmf_state.stmf_default_lu_state !=
15344b31676fSsrivijitha dugganapalli 			    STMF_STATE_ONLINE)
1535fcf3ce44SJohn Forte 				continue;
1536fcf3ce44SJohn Forte 			(void) stmf_ctl(STMF_CMD_LU_ONLINE, ilu->ilu_lu, &ssi);
1537fcf3ce44SJohn Forte 		}
1538fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
1539fcf3ce44SJohn Forte 		stmf_state.stmf_inventory_locked = 0;
1540fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1541fcf3ce44SJohn Forte 		return (0);
1542fcf3ce44SJohn Forte 	}
1543fcf3ce44SJohn Forte 
1544fcf3ce44SJohn Forte 	/* svc_state is STMF_STATE_ONLINE here */
1545fcf3ce44SJohn Forte 	if ((std->state != STMF_STATE_OFFLINE) ||
1546fcf3ce44SJohn Forte 	    (std->config_state == STMF_CONFIG_INIT)) {
1547fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
1548fcf3ce44SJohn Forte 		return (EACCES);
1549fcf3ce44SJohn Forte 	}
1550fcf3ce44SJohn Forte 
1551fcf3ce44SJohn Forte 	stmf_state.stmf_inventory_locked = 1;
1552fcf3ce44SJohn Forte 	stmf_state.stmf_service_running = 0;
1553640428aeSSue Gleeson 
1554fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
1555fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1556fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
1557fcf3ce44SJohn Forte 		if (ilport->ilport_state != STMF_STATE_ONLINE)
1558fcf3ce44SJohn Forte 			continue;
1559fcf3ce44SJohn Forte 		(void) stmf_ctl(STMF_CMD_LPORT_OFFLINE,
1560fcf3ce44SJohn Forte 		    ilport->ilport_lport, &ssi);
1561fcf3ce44SJohn Forte 	}
1562fcf3ce44SJohn Forte 
1563fcf3ce44SJohn Forte 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
1564fcf3ce44SJohn Forte 	    ilu = ilu->ilu_next) {
1565fcf3ce44SJohn Forte 		if (ilu->ilu_state != STMF_STATE_ONLINE)
1566fcf3ce44SJohn Forte 			continue;
1567fcf3ce44SJohn Forte 		(void) stmf_ctl(STMF_CMD_LU_OFFLINE, ilu->ilu_lu, &ssi);
1568fcf3ce44SJohn Forte 	}
1569fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
1570fcf3ce44SJohn Forte 	stmf_state.stmf_inventory_locked = 0;
1571fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
1572fcf3ce44SJohn Forte 	return (0);
1573fcf3ce44SJohn Forte }
1574fcf3ce44SJohn Forte 
1575fcf3ce44SJohn Forte static int
stmf_get_stmf_state(stmf_state_desc_t * std)1576fcf3ce44SJohn Forte stmf_get_stmf_state(stmf_state_desc_t *std)
1577fcf3ce44SJohn Forte {
1578fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
1579fcf3ce44SJohn Forte 	std->state = stmf_get_service_state();
1580fcf3ce44SJohn Forte 	std->config_state = stmf_state.stmf_config_state;
1581fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
1582fcf3ce44SJohn Forte 
1583fcf3ce44SJohn Forte 	return (0);
1584fcf3ce44SJohn Forte }
158509409df0SJeff Biseda 
158645039663SJohn Forte /*
158745039663SJohn Forte  * handles registration message from pppt for a logical unit
158845039663SJohn Forte  */
158945039663SJohn Forte stmf_status_t
stmf_ic_lu_reg(stmf_ic_reg_dereg_lun_msg_t * msg,uint32_t type)159045039663SJohn Forte stmf_ic_lu_reg(stmf_ic_reg_dereg_lun_msg_t *msg, uint32_t type)
159145039663SJohn Forte {
159245039663SJohn Forte 	stmf_i_lu_provider_t	*ilp;
159345039663SJohn Forte 	stmf_lu_provider_t	*lp;
159445039663SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
159545039663SJohn Forte 	for (ilp = stmf_state.stmf_ilplist; ilp != NULL; ilp = ilp->ilp_next) {
159645039663SJohn Forte 		if (strcmp(msg->icrl_lu_provider_name,
159745039663SJohn Forte 		    ilp->ilp_lp->lp_name) == 0) {
159845039663SJohn Forte 			lp = ilp->ilp_lp;
159945039663SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
160045039663SJohn Forte 			lp->lp_proxy_msg(msg->icrl_lun_id, msg->icrl_cb_arg,
160145039663SJohn Forte 			    msg->icrl_cb_arg_len, type);
160245039663SJohn Forte 			return (STMF_SUCCESS);
160345039663SJohn Forte 		}
160445039663SJohn Forte 	}
160545039663SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
160645039663SJohn Forte 	return (STMF_SUCCESS);
160745039663SJohn Forte }
160845039663SJohn Forte 
160945039663SJohn Forte /*
161045039663SJohn Forte  * handles de-registration message from pppt for a logical unit
161145039663SJohn Forte  */
161245039663SJohn Forte stmf_status_t
stmf_ic_lu_dereg(stmf_ic_reg_dereg_lun_msg_t * msg)161345039663SJohn Forte stmf_ic_lu_dereg(stmf_ic_reg_dereg_lun_msg_t *msg)
161445039663SJohn Forte {
161545039663SJohn Forte 	stmf_i_lu_provider_t	*ilp;
161645039663SJohn Forte 	stmf_lu_provider_t	*lp;
161745039663SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
161845039663SJohn Forte 	for (ilp = stmf_state.stmf_ilplist; ilp != NULL; ilp = ilp->ilp_next) {
161945039663SJohn Forte 		if (strcmp(msg->icrl_lu_provider_name,
162045039663SJohn Forte 		    ilp->ilp_lp->lp_name) == 0) {
162145039663SJohn Forte 			lp = ilp->ilp_lp;
162245039663SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
162345039663SJohn Forte 			lp->lp_proxy_msg(msg->icrl_lun_id, NULL, 0,
162445039663SJohn Forte 			    STMF_MSG_LU_DEREGISTER);
162545039663SJohn Forte 			return (STMF_SUCCESS);
162645039663SJohn Forte 		}
162745039663SJohn Forte 	}
162845039663SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
162945039663SJohn Forte 	return (STMF_SUCCESS);
163045039663SJohn Forte }
163145039663SJohn Forte 
163245039663SJohn Forte /*
163345039663SJohn Forte  * helper function to find a task that matches a task_msgid
163445039663SJohn Forte  */
163545039663SJohn Forte scsi_task_t *
find_task_from_msgid(uint8_t * lu_id,stmf_ic_msgid_t task_msgid)163645039663SJohn Forte find_task_from_msgid(uint8_t *lu_id, stmf_ic_msgid_t task_msgid)
163745039663SJohn Forte {
163845039663SJohn Forte 	stmf_i_lu_t *ilu;
163945039663SJohn Forte 	stmf_i_scsi_task_t *itask;
164045039663SJohn Forte 
164145039663SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
164245039663SJohn Forte 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
164345039663SJohn Forte 		if (bcmp(lu_id, ilu->ilu_lu->lu_id->ident, 16) == 0) {
164445039663SJohn Forte 			break;
164545039663SJohn Forte 		}
164645039663SJohn Forte 	}
164745039663SJohn Forte 
164845039663SJohn Forte 	if (ilu == NULL) {
164945039663SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
165045039663SJohn Forte 		return (NULL);
165145039663SJohn Forte 	}
165245039663SJohn Forte 
165345039663SJohn Forte 	mutex_enter(&ilu->ilu_task_lock);
165445039663SJohn Forte 	for (itask = ilu->ilu_tasks; itask != NULL;
165545039663SJohn Forte 	    itask = itask->itask_lu_next) {
165661dfa509SRick McNeal 		mutex_enter(&itask->itask_mutex);
165745039663SJohn Forte 		if (itask->itask_flags & (ITASK_IN_FREE_LIST |
165845039663SJohn Forte 		    ITASK_BEING_ABORTED)) {
165961dfa509SRick McNeal 			mutex_exit(&itask->itask_mutex);
166045039663SJohn Forte 			continue;
166145039663SJohn Forte 		}
166261dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
166345039663SJohn Forte 		if (itask->itask_proxy_msg_id == task_msgid) {
166445039663SJohn Forte 			break;
166545039663SJohn Forte 		}
166645039663SJohn Forte 	}
166745039663SJohn Forte 	mutex_exit(&ilu->ilu_task_lock);
166845039663SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
166945039663SJohn Forte 
167045039663SJohn Forte 	if (itask != NULL) {
167145039663SJohn Forte 		return (itask->itask_task);
167245039663SJohn Forte 	} else {
167345039663SJohn Forte 		/* task not found. Likely already aborted. */
167445039663SJohn Forte 		return (NULL);
167545039663SJohn Forte 	}
167645039663SJohn Forte }
167745039663SJohn Forte 
167845039663SJohn Forte /*
167945039663SJohn Forte  * message received from pppt/ic
168045039663SJohn Forte  */
168145039663SJohn Forte stmf_status_t
stmf_msg_rx(stmf_ic_msg_t * msg)168245039663SJohn Forte stmf_msg_rx(stmf_ic_msg_t *msg)
168345039663SJohn Forte {
168445039663SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
168545039663SJohn Forte 	if (stmf_state.stmf_alua_state != 1) {
168645039663SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
168745039663SJohn Forte 		cmn_err(CE_WARN, "stmf alua state is disabled");
168845039663SJohn Forte 		ic_msg_free(msg);
168945039663SJohn Forte 		return (STMF_FAILURE);
169045039663SJohn Forte 	}
169145039663SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
169245039663SJohn Forte 
169345039663SJohn Forte 	switch (msg->icm_msg_type) {
169445039663SJohn Forte 		case STMF_ICM_REGISTER_LUN:
169545039663SJohn Forte 			(void) stmf_ic_lu_reg(
169645039663SJohn Forte 			    (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg,
169745039663SJohn Forte 			    STMF_MSG_LU_REGISTER);
169845039663SJohn Forte 			break;
169945039663SJohn Forte 		case STMF_ICM_LUN_ACTIVE:
170045039663SJohn Forte 			(void) stmf_ic_lu_reg(
170145039663SJohn Forte 			    (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg,
170245039663SJohn Forte 			    STMF_MSG_LU_ACTIVE);
170345039663SJohn Forte 			break;
170445039663SJohn Forte 		case STMF_ICM_DEREGISTER_LUN:
170545039663SJohn Forte 			(void) stmf_ic_lu_dereg(
170645039663SJohn Forte 			    (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg);
170745039663SJohn Forte 			break;
170845039663SJohn Forte 		case STMF_ICM_SCSI_DATA:
170945039663SJohn Forte 			(void) stmf_ic_rx_scsi_data(
171045039663SJohn Forte 			    (stmf_ic_scsi_data_msg_t *)msg->icm_msg);
171145039663SJohn Forte 			break;
171245039663SJohn Forte 		case STMF_ICM_SCSI_STATUS:
171345039663SJohn Forte 			(void) stmf_ic_rx_scsi_status(
171445039663SJohn Forte 			    (stmf_ic_scsi_status_msg_t *)msg->icm_msg);
171545039663SJohn Forte 			break;
171645039663SJohn Forte 		case STMF_ICM_STATUS:
171745039663SJohn Forte 			(void) stmf_ic_rx_status(
171845039663SJohn Forte 			    (stmf_ic_status_msg_t *)msg->icm_msg);
171945039663SJohn Forte 			break;
172045039663SJohn Forte 		default:
172145039663SJohn Forte 			cmn_err(CE_WARN, "unknown message received %d",
172245039663SJohn Forte 			    msg->icm_msg_type);
172345039663SJohn Forte 			ic_msg_free(msg);
172445039663SJohn Forte 			return (STMF_FAILURE);
172545039663SJohn Forte 	}
172645039663SJohn Forte 	ic_msg_free(msg);
172745039663SJohn Forte 	return (STMF_SUCCESS);
172845039663SJohn Forte }
172945039663SJohn Forte 
173045039663SJohn Forte stmf_status_t
stmf_ic_rx_status(stmf_ic_status_msg_t * msg)173145039663SJohn Forte stmf_ic_rx_status(stmf_ic_status_msg_t *msg)
173245039663SJohn Forte {
173345039663SJohn Forte 	stmf_i_local_port_t *ilport;
173445039663SJohn Forte 
173545039663SJohn Forte 	if (msg->ics_msg_type != STMF_ICM_REGISTER_PROXY_PORT) {
173645039663SJohn Forte 		/* for now, ignore other message status */
173745039663SJohn Forte 		return (STMF_SUCCESS);
173845039663SJohn Forte 	}
173945039663SJohn Forte 
174045039663SJohn Forte 	if (msg->ics_status != STMF_SUCCESS) {
174145039663SJohn Forte 		return (STMF_SUCCESS);
174245039663SJohn Forte 	}
174345039663SJohn Forte 
174445039663SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
174545039663SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
174645039663SJohn Forte 	    ilport = ilport->ilport_next) {
174745039663SJohn Forte 		if (msg->ics_msgid == ilport->ilport_reg_msgid) {
174845039663SJohn Forte 			ilport->ilport_proxy_registered = 1;
174945039663SJohn Forte 			break;
175045039663SJohn Forte 		}
175145039663SJohn Forte 	}
175245039663SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
175345039663SJohn Forte 	return (STMF_SUCCESS);
175445039663SJohn Forte }
175545039663SJohn Forte 
175645039663SJohn Forte /*
175745039663SJohn Forte  * handles scsi status message from pppt
175845039663SJohn Forte  */
175945039663SJohn Forte stmf_status_t
stmf_ic_rx_scsi_status(stmf_ic_scsi_status_msg_t * msg)176045039663SJohn Forte stmf_ic_rx_scsi_status(stmf_ic_scsi_status_msg_t *msg)
176145039663SJohn Forte {
176245039663SJohn Forte 	scsi_task_t *task;
176345039663SJohn Forte 
1764cbdc6dc7SJohn Forte 	/* is this a task management command */
1765cbdc6dc7SJohn Forte 	if (msg->icss_task_msgid & MSG_ID_TM_BIT) {
1766cbdc6dc7SJohn Forte 		return (STMF_SUCCESS);
1767cbdc6dc7SJohn Forte 	}
1768cbdc6dc7SJohn Forte 
176945039663SJohn Forte 	task = find_task_from_msgid(msg->icss_lun_id, msg->icss_task_msgid);
177045039663SJohn Forte 
177145039663SJohn Forte 	if (task == NULL) {
177245039663SJohn Forte 		return (STMF_SUCCESS);
177345039663SJohn Forte 	}
177445039663SJohn Forte 
177545039663SJohn Forte 	task->task_scsi_status = msg->icss_status;
177645039663SJohn Forte 	task->task_sense_data = msg->icss_sense;
177745039663SJohn Forte 	task->task_sense_length = msg->icss_sense_len;
177845039663SJohn Forte 	(void) stmf_send_scsi_status(task, STMF_IOF_LU_DONE);
177945039663SJohn Forte 
178045039663SJohn Forte 	return (STMF_SUCCESS);
178145039663SJohn Forte }
178245039663SJohn Forte 
178345039663SJohn Forte /*
178445039663SJohn Forte  * handles scsi data message from pppt
178545039663SJohn Forte  */
178645039663SJohn Forte stmf_status_t
stmf_ic_rx_scsi_data(stmf_ic_scsi_data_msg_t * msg)178745039663SJohn Forte stmf_ic_rx_scsi_data(stmf_ic_scsi_data_msg_t *msg)
178845039663SJohn Forte {
178945039663SJohn Forte 	stmf_i_scsi_task_t *itask;
179045039663SJohn Forte 	scsi_task_t *task;
179145039663SJohn Forte 	stmf_xfer_data_t *xd = NULL;
179245039663SJohn Forte 	stmf_data_buf_t *dbuf;
179345039663SJohn Forte 	uint32_t sz, minsz, xd_sz, asz;
179445039663SJohn Forte 
1795cbdc6dc7SJohn Forte 	/* is this a task management command */
1796cbdc6dc7SJohn Forte 	if (msg->icsd_task_msgid & MSG_ID_TM_BIT) {
1797cbdc6dc7SJohn Forte 		return (STMF_SUCCESS);
1798cbdc6dc7SJohn Forte 	}
1799cbdc6dc7SJohn Forte 
180045039663SJohn Forte 	task = find_task_from_msgid(msg->icsd_lun_id, msg->icsd_task_msgid);
180145039663SJohn Forte 	if (task == NULL) {
180245039663SJohn Forte 		stmf_ic_msg_t *ic_xfer_done_msg = NULL;
180345039663SJohn Forte 		static uint64_t data_msg_id;
180445039663SJohn Forte 		stmf_status_t ic_ret = STMF_FAILURE;
180545039663SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
180645039663SJohn Forte 		data_msg_id = stmf_proxy_msg_id++;
180745039663SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
180845039663SJohn Forte 		/*
180945039663SJohn Forte 		 * send xfer done status to pppt
181045039663SJohn Forte 		 * for now, set the session id to 0 as we cannot
181145039663SJohn Forte 		 * ascertain it since we cannot find the task
181245039663SJohn Forte 		 */
181345039663SJohn Forte 		ic_xfer_done_msg = ic_scsi_data_xfer_done_msg_alloc(
181445039663SJohn Forte 		    msg->icsd_task_msgid, 0, STMF_FAILURE, data_msg_id);
181545039663SJohn Forte 		if (ic_xfer_done_msg) {
181645039663SJohn Forte 			ic_ret = ic_tx_msg(ic_xfer_done_msg);
181745039663SJohn Forte 			if (ic_ret != STMF_IC_MSG_SUCCESS) {
181845039663SJohn Forte 				cmn_err(CE_WARN, "unable to xmit proxy msg");
181945039663SJohn Forte 			}
182045039663SJohn Forte 		}
182145039663SJohn Forte 		return (STMF_FAILURE);
182245039663SJohn Forte 	}
182345039663SJohn Forte 
182445039663SJohn Forte 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
182545039663SJohn Forte 	dbuf = itask->itask_proxy_dbuf;
182645039663SJohn Forte 
182791159e90SJohn Forte 	task->task_cmd_xfer_length += msg->icsd_data_len;
182845039663SJohn Forte 
182945039663SJohn Forte 	if (task->task_additional_flags &
183045039663SJohn Forte 	    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
183145039663SJohn Forte 		task->task_expected_xfer_length =
183245039663SJohn Forte 		    task->task_cmd_xfer_length;
183345039663SJohn Forte 	}
183445039663SJohn Forte 
183545039663SJohn Forte 	sz = min(task->task_expected_xfer_length,
183645039663SJohn Forte 	    task->task_cmd_xfer_length);
183745039663SJohn Forte 
183845039663SJohn Forte 	xd_sz = msg->icsd_data_len;
183945039663SJohn Forte 	asz = xd_sz + sizeof (*xd) - 4;
184045039663SJohn Forte 	xd = (stmf_xfer_data_t *)kmem_zalloc(asz, KM_NOSLEEP);
184145039663SJohn Forte 
184245039663SJohn Forte 	if (xd == NULL) {
184345039663SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
184445039663SJohn Forte 		    STMF_ALLOC_FAILURE, NULL);
184545039663SJohn Forte 		return (STMF_FAILURE);
184645039663SJohn Forte 	}
184745039663SJohn Forte 
184845039663SJohn Forte 	xd->alloc_size = asz;
184945039663SJohn Forte 	xd->size_left = xd_sz;
185045039663SJohn Forte 	bcopy(msg->icsd_data, xd->buf, xd_sz);
185145039663SJohn Forte 
185245039663SJohn Forte 	sz = min(sz, xd->size_left);
185345039663SJohn Forte 	xd->size_left = sz;
185445039663SJohn Forte 	minsz = min(512, sz);
185545039663SJohn Forte 
185645039663SJohn Forte 	if (dbuf == NULL)
185745039663SJohn Forte 		dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0);
185845039663SJohn Forte 	if (dbuf == NULL) {
185945039663SJohn Forte 		kmem_free(xd, xd->alloc_size);
186045039663SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
186145039663SJohn Forte 		    STMF_ALLOC_FAILURE, NULL);
186245039663SJohn Forte 		return (STMF_FAILURE);
186345039663SJohn Forte 	}
186445039663SJohn Forte 	dbuf->db_lu_private = xd;
186591159e90SJohn Forte 	dbuf->db_relative_offset = task->task_nbytes_transferred;
186691159e90SJohn Forte 	stmf_xd_to_dbuf(dbuf, 0);
186745039663SJohn Forte 
186845039663SJohn Forte 	dbuf->db_flags = DB_DIRECTION_TO_RPORT;
186945039663SJohn Forte 	(void) stmf_xfer_data(task, dbuf, 0);
187045039663SJohn Forte 	return (STMF_SUCCESS);
187145039663SJohn Forte }
187245039663SJohn Forte 
187345039663SJohn Forte stmf_status_t
stmf_proxy_scsi_cmd(scsi_task_t * task,stmf_data_buf_t * dbuf)187445039663SJohn Forte stmf_proxy_scsi_cmd(scsi_task_t *task, stmf_data_buf_t *dbuf)
187545039663SJohn Forte {
187645039663SJohn Forte 	stmf_i_scsi_task_t *itask =
187745039663SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
187845039663SJohn Forte 	stmf_i_local_port_t *ilport =
187945039663SJohn Forte 	    (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
188045039663SJohn Forte 	stmf_ic_msg_t *ic_cmd_msg;
188145039663SJohn Forte 	stmf_ic_msg_status_t ic_ret;
188245039663SJohn Forte 	stmf_status_t ret = STMF_FAILURE;
188345039663SJohn Forte 
1884437be372SJohn Forte 	if (stmf_state.stmf_alua_state != 1) {
1885437be372SJohn Forte 		cmn_err(CE_WARN, "stmf alua state is disabled");
188645039663SJohn Forte 		return (STMF_FAILURE);
188745039663SJohn Forte 	}
188845039663SJohn Forte 
1889437be372SJohn Forte 	if (ilport->ilport_proxy_registered == 0) {
189045039663SJohn Forte 		return (STMF_FAILURE);
189145039663SJohn Forte 	}
189245039663SJohn Forte 
189345039663SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
189445039663SJohn Forte 	itask->itask_proxy_msg_id = stmf_proxy_msg_id++;
189545039663SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
189645039663SJohn Forte 	itask->itask_proxy_dbuf = dbuf;
1897437be372SJohn Forte 
1898437be372SJohn Forte 	/*
1899437be372SJohn Forte 	 * stmf will now take over the task handling for this task
1900437be372SJohn Forte 	 * but it still needs to be treated differently from other
1901cbdc6dc7SJohn Forte 	 * default handled tasks, hence the ITASK_PROXY_TASK.
1902cbdc6dc7SJohn Forte 	 * If this is a task management function, we're really just
1903cbdc6dc7SJohn Forte 	 * duping the command to the peer. Set the TM bit so that
1904cbdc6dc7SJohn Forte 	 * we can recognize this on return since we won't be completing
1905cbdc6dc7SJohn Forte 	 * the proxied task in that case.
1906437be372SJohn Forte 	 */
190761dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
1908cbdc6dc7SJohn Forte 	if (task->task_mgmt_function) {
1909cbdc6dc7SJohn Forte 		itask->itask_proxy_msg_id |= MSG_ID_TM_BIT;
1910cbdc6dc7SJohn Forte 	} else {
191161dfa509SRick McNeal 		if (itask->itask_flags & ITASK_BEING_ABORTED) {
191261dfa509SRick McNeal 			mutex_exit(&itask->itask_mutex);
1913fdff2149SJohn Forte 			return (STMF_FAILURE);
191461dfa509SRick McNeal 		}
191561dfa509SRick McNeal 		itask->itask_flags |= ITASK_DEFAULT_HANDLING | ITASK_PROXY_TASK;
1916cbdc6dc7SJohn Forte 	}
191745039663SJohn Forte 	if (dbuf) {
191845039663SJohn Forte 		ic_cmd_msg = ic_scsi_cmd_msg_alloc(itask->itask_proxy_msg_id,
191945039663SJohn Forte 		    task, dbuf->db_data_size, dbuf->db_sglist[0].seg_addr,
192045039663SJohn Forte 		    itask->itask_proxy_msg_id);
192145039663SJohn Forte 	} else {
192245039663SJohn Forte 		ic_cmd_msg = ic_scsi_cmd_msg_alloc(itask->itask_proxy_msg_id,
192345039663SJohn Forte 		    task, 0, NULL, itask->itask_proxy_msg_id);
192445039663SJohn Forte 	}
192561dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
192645039663SJohn Forte 	if (ic_cmd_msg) {
192745039663SJohn Forte 		ic_ret = ic_tx_msg(ic_cmd_msg);
192845039663SJohn Forte 		if (ic_ret == STMF_IC_MSG_SUCCESS) {
192945039663SJohn Forte 			ret = STMF_SUCCESS;
193045039663SJohn Forte 		}
193145039663SJohn Forte 	}
193245039663SJohn Forte 	return (ret);
193345039663SJohn Forte }
193445039663SJohn Forte 
193545039663SJohn Forte 
193645039663SJohn Forte stmf_status_t
pppt_modload()193745039663SJohn Forte pppt_modload()
193845039663SJohn Forte {
193945039663SJohn Forte 	int error;
194045039663SJohn Forte 
194145039663SJohn Forte 	if (pppt_mod == NULL && ((pppt_mod =
194245039663SJohn Forte 	    ddi_modopen("drv/pppt", KRTLD_MODE_FIRST, &error)) == NULL)) {
194345039663SJohn Forte 		cmn_err(CE_WARN, "Unable to load pppt");
194445039663SJohn Forte 		return (STMF_FAILURE);
194545039663SJohn Forte 	}
194645039663SJohn Forte 
194745039663SJohn Forte 	if (ic_reg_port_msg_alloc == NULL && ((ic_reg_port_msg_alloc =
194845039663SJohn Forte 	    (stmf_ic_reg_port_msg_alloc_func_t)
194945039663SJohn Forte 	    ddi_modsym(pppt_mod, "stmf_ic_reg_port_msg_alloc",
195045039663SJohn Forte 	    &error)) == NULL)) {
195145039663SJohn Forte 		cmn_err(CE_WARN,
195245039663SJohn Forte 		    "Unable to find symbol - stmf_ic_reg_port_msg_alloc");
195345039663SJohn Forte 		return (STMF_FAILURE);
195445039663SJohn Forte 	}
195545039663SJohn Forte 
195645039663SJohn Forte 
195745039663SJohn Forte 	if (ic_dereg_port_msg_alloc == NULL && ((ic_dereg_port_msg_alloc =
195845039663SJohn Forte 	    (stmf_ic_dereg_port_msg_alloc_func_t)
195945039663SJohn Forte 	    ddi_modsym(pppt_mod, "stmf_ic_dereg_port_msg_alloc",
196045039663SJohn Forte 	    &error)) == NULL)) {
196145039663SJohn Forte 		cmn_err(CE_WARN,
196245039663SJohn Forte 		    "Unable to find symbol - stmf_ic_dereg_port_msg_alloc");
196345039663SJohn Forte 		return (STMF_FAILURE);
196445039663SJohn Forte 	}
196545039663SJohn Forte 
196645039663SJohn Forte 	if (ic_reg_lun_msg_alloc == NULL && ((ic_reg_lun_msg_alloc =
196745039663SJohn Forte 	    (stmf_ic_reg_lun_msg_alloc_func_t)
196845039663SJohn Forte 	    ddi_modsym(pppt_mod, "stmf_ic_reg_lun_msg_alloc",
196945039663SJohn Forte 	    &error)) == NULL)) {
197045039663SJohn Forte 		cmn_err(CE_WARN,
197145039663SJohn Forte 		    "Unable to find symbol - stmf_ic_reg_lun_msg_alloc");
197245039663SJohn Forte 		return (STMF_FAILURE);
197345039663SJohn Forte 	}
197445039663SJohn Forte 
197545039663SJohn Forte 	if (ic_lun_active_msg_alloc == NULL && ((ic_lun_active_msg_alloc =
197645039663SJohn Forte 	    (stmf_ic_lun_active_msg_alloc_func_t)
197745039663SJohn Forte 	    ddi_modsym(pppt_mod, "stmf_ic_lun_active_msg_alloc",
197845039663SJohn Forte 	    &error)) == NULL)) {
197945039663SJohn Forte 		cmn_err(CE_WARN,
198045039663SJohn Forte 		    "Unable to find symbol - stmf_ic_lun_active_msg_alloc");
198145039663SJohn Forte 		return (STMF_FAILURE);
198245039663SJohn Forte 	}
198345039663SJohn Forte 
198445039663SJohn Forte 	if (ic_dereg_lun_msg_alloc == NULL && ((ic_dereg_lun_msg_alloc =
198545039663SJohn Forte 	    (stmf_ic_dereg_lun_msg_alloc_func_t)
198645039663SJohn Forte 	    ddi_modsym(pppt_mod, "stmf_ic_dereg_lun_msg_alloc",
198745039663SJohn Forte 	    &error)) == NULL)) {
198845039663SJohn Forte 		cmn_err(CE_WARN,
198945039663SJohn Forte 		    "Unable to find symbol - stmf_ic_dereg_lun_msg_alloc");
199045039663SJohn Forte 		return (STMF_FAILURE);
199145039663SJohn Forte 	}
199245039663SJohn Forte 
199345039663SJohn Forte 	if (ic_scsi_cmd_msg_alloc == NULL && ((ic_scsi_cmd_msg_alloc =
199445039663SJohn Forte 	    (stmf_ic_scsi_cmd_msg_alloc_func_t)
199545039663SJohn Forte 	    ddi_modsym(pppt_mod, "stmf_ic_scsi_cmd_msg_alloc",
199645039663SJohn Forte 	    &error)) == NULL)) {
199745039663SJohn Forte 		cmn_err(CE_WARN,
199845039663SJohn Forte 		    "Unable to find symbol - stmf_ic_scsi_cmd_msg_alloc");
199945039663SJohn Forte 		return (STMF_FAILURE);
200045039663SJohn Forte 	}
200145039663SJohn Forte 
200245039663SJohn Forte 	if (ic_scsi_data_xfer_done_msg_alloc == NULL &&
200345039663SJohn Forte 	    ((ic_scsi_data_xfer_done_msg_alloc =
200445039663SJohn Forte 	    (stmf_ic_scsi_data_xfer_done_msg_alloc_func_t)
200545039663SJohn Forte 	    ddi_modsym(pppt_mod, "stmf_ic_scsi_data_xfer_done_msg_alloc",
200645039663SJohn Forte 	    &error)) == NULL)) {
200745039663SJohn Forte 		cmn_err(CE_WARN,
200845039663SJohn Forte 		    "Unable to find symbol -"
200945039663SJohn Forte 		    "stmf_ic_scsi_data_xfer_done_msg_alloc");
201045039663SJohn Forte 		return (STMF_FAILURE);
201145039663SJohn Forte 	}
201245039663SJohn Forte 
201345039663SJohn Forte 	if (ic_session_reg_msg_alloc == NULL &&
201445039663SJohn Forte 	    ((ic_session_reg_msg_alloc =
201545039663SJohn Forte 	    (stmf_ic_session_create_msg_alloc_func_t)
201645039663SJohn Forte 	    ddi_modsym(pppt_mod, "stmf_ic_session_create_msg_alloc",
201745039663SJohn Forte 	    &error)) == NULL)) {
201845039663SJohn Forte 		cmn_err(CE_WARN,
201945039663SJohn Forte 		    "Unable to find symbol -"
202045039663SJohn Forte 		    "stmf_ic_session_create_msg_alloc");
202145039663SJohn Forte 		return (STMF_FAILURE);
202245039663SJohn Forte 	}
202345039663SJohn Forte 
202445039663SJohn Forte 	if (ic_session_dereg_msg_alloc == NULL &&
202545039663SJohn Forte 	    ((ic_session_dereg_msg_alloc =
202645039663SJohn Forte 	    (stmf_ic_session_destroy_msg_alloc_func_t)
202745039663SJohn Forte 	    ddi_modsym(pppt_mod, "stmf_ic_session_destroy_msg_alloc",
202845039663SJohn Forte 	    &error)) == NULL)) {
202945039663SJohn Forte 		cmn_err(CE_WARN,
203045039663SJohn Forte 		    "Unable to find symbol -"
203145039663SJohn Forte 		    "stmf_ic_session_destroy_msg_alloc");
203245039663SJohn Forte 		return (STMF_FAILURE);
203345039663SJohn Forte 	}
203445039663SJohn Forte 
203545039663SJohn Forte 	if (ic_tx_msg == NULL && ((ic_tx_msg =
203645039663SJohn Forte 	    (stmf_ic_tx_msg_func_t)ddi_modsym(pppt_mod, "stmf_ic_tx_msg",
203745039663SJohn Forte 	    &error)) == NULL)) {
203845039663SJohn Forte 		cmn_err(CE_WARN, "Unable to find symbol - stmf_ic_tx_msg");
203945039663SJohn Forte 		return (STMF_FAILURE);
204045039663SJohn Forte 	}
204145039663SJohn Forte 
204245039663SJohn Forte 	if (ic_msg_free == NULL && ((ic_msg_free =
204345039663SJohn Forte 	    (stmf_ic_msg_free_func_t)ddi_modsym(pppt_mod, "stmf_ic_msg_free",
204445039663SJohn Forte 	    &error)) == NULL)) {
204545039663SJohn Forte 		cmn_err(CE_WARN, "Unable to find symbol - stmf_ic_msg_free");
204645039663SJohn Forte 		return (STMF_FAILURE);
204745039663SJohn Forte 	}
204845039663SJohn Forte 	return (STMF_SUCCESS);
204945039663SJohn Forte }
205045039663SJohn Forte 
205145039663SJohn Forte static void
stmf_get_alua_state(stmf_alua_state_desc_t * alua_state)205245039663SJohn Forte stmf_get_alua_state(stmf_alua_state_desc_t *alua_state)
205345039663SJohn Forte {
205445039663SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
205545039663SJohn Forte 	alua_state->alua_node = stmf_state.stmf_alua_node;
205645039663SJohn Forte 	alua_state->alua_state = stmf_state.stmf_alua_state;
205745039663SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
205845039663SJohn Forte }
205945039663SJohn Forte 
206045039663SJohn Forte 
206145039663SJohn Forte static int
stmf_set_alua_state(stmf_alua_state_desc_t * alua_state)206245039663SJohn Forte stmf_set_alua_state(stmf_alua_state_desc_t *alua_state)
206345039663SJohn Forte {
206445039663SJohn Forte 	stmf_i_local_port_t *ilport;
206545039663SJohn Forte 	stmf_i_lu_t *ilu;
206645039663SJohn Forte 	stmf_lu_t *lu;
206745039663SJohn Forte 	stmf_ic_msg_status_t ic_ret;
206845039663SJohn Forte 	stmf_ic_msg_t *ic_reg_lun, *ic_reg_port;
206945039663SJohn Forte 	stmf_local_port_t *lport;
207045039663SJohn Forte 	int ret = 0;
207145039663SJohn Forte 
207245039663SJohn Forte 	if (alua_state->alua_state > 1 || alua_state->alua_node > 1) {
207345039663SJohn Forte 		return (EINVAL);
207445039663SJohn Forte 	}
207545039663SJohn Forte 
207645039663SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
207745039663SJohn Forte 	if (alua_state->alua_state == 1) {
207845039663SJohn Forte 		if (pppt_modload() == STMF_FAILURE) {
207945039663SJohn Forte 			ret = EIO;
208045039663SJohn Forte 			goto err;
208145039663SJohn Forte 		}
208245039663SJohn Forte 		if (alua_state->alua_node != 0) {
208345039663SJohn Forte 			/* reset existing rtpids to new base */
208445039663SJohn Forte 			stmf_rtpid_counter = 255;
208545039663SJohn Forte 		}
208645039663SJohn Forte 		stmf_state.stmf_alua_node = alua_state->alua_node;
208745039663SJohn Forte 		stmf_state.stmf_alua_state = 1;
208845039663SJohn Forte 		/* register existing local ports with ppp */
208945039663SJohn Forte 		for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
209045039663SJohn Forte 		    ilport = ilport->ilport_next) {
2091cd36db67SJohn Forte 			/* skip standby ports and non-alua participants */
2092cd36db67SJohn Forte 			if (ilport->ilport_standby == 1 ||
2093cd36db67SJohn Forte 			    ilport->ilport_alua == 0) {
209445039663SJohn Forte 				continue;
209545039663SJohn Forte 			}
209645039663SJohn Forte 			if (alua_state->alua_node != 0) {
209745039663SJohn Forte 				ilport->ilport_rtpid =
20981a5e258fSJosef 'Jeff' Sipek 				    atomic_inc_16_nv(&stmf_rtpid_counter);
209945039663SJohn Forte 			}
210045039663SJohn Forte 			lport = ilport->ilport_lport;
210145039663SJohn Forte 			ic_reg_port = ic_reg_port_msg_alloc(
210245039663SJohn Forte 			    lport->lport_id, ilport->ilport_rtpid,
210345039663SJohn Forte 			    0, NULL, stmf_proxy_msg_id);
210445039663SJohn Forte 			if (ic_reg_port) {
210545039663SJohn Forte 				ic_ret = ic_tx_msg(ic_reg_port);
210645039663SJohn Forte 				if (ic_ret == STMF_IC_MSG_SUCCESS) {
210745039663SJohn Forte 					ilport->ilport_reg_msgid =
210845039663SJohn Forte 					    stmf_proxy_msg_id++;
210945039663SJohn Forte 				} else {
211045039663SJohn Forte 					cmn_err(CE_WARN,
211145039663SJohn Forte 					    "error on port registration "
211245039663SJohn Forte 					    "port - %s",
211345039663SJohn Forte 					    ilport->ilport_kstat_tgt_name);
211445039663SJohn Forte 				}
211545039663SJohn Forte 			}
211645039663SJohn Forte 		}
211745039663SJohn Forte 		/* register existing logical units */
211845039663SJohn Forte 		for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
211945039663SJohn Forte 		    ilu = ilu->ilu_next) {
212045039663SJohn Forte 			if (ilu->ilu_access != STMF_LU_ACTIVE) {
212145039663SJohn Forte 				continue;
212245039663SJohn Forte 			}
212345039663SJohn Forte 			/* register with proxy module */
212445039663SJohn Forte 			lu = ilu->ilu_lu;
212545039663SJohn Forte 			if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
212645039663SJohn Forte 			    lu->lu_lp->lp_alua_support) {
212745039663SJohn Forte 				ilu->ilu_alua = 1;
212845039663SJohn Forte 				/* allocate the register message */
212945039663SJohn Forte 				ic_reg_lun = ic_reg_lun_msg_alloc(
213045039663SJohn Forte 				    lu->lu_id->ident, lu->lu_lp->lp_name,
213145039663SJohn Forte 				    lu->lu_proxy_reg_arg_len,
213245039663SJohn Forte 				    (uint8_t *)lu->lu_proxy_reg_arg,
213345039663SJohn Forte 				    stmf_proxy_msg_id);
213445039663SJohn Forte 				/* send the message */
213545039663SJohn Forte 				if (ic_reg_lun) {
213645039663SJohn Forte 					ic_ret = ic_tx_msg(ic_reg_lun);
213745039663SJohn Forte 					if (ic_ret == STMF_IC_MSG_SUCCESS) {
213845039663SJohn Forte 						stmf_proxy_msg_id++;
213945039663SJohn Forte 					}
214045039663SJohn Forte 				}
214145039663SJohn Forte 			}
214245039663SJohn Forte 		}
214345039663SJohn Forte 	} else {
214445039663SJohn Forte 		stmf_state.stmf_alua_state = 0;
214545039663SJohn Forte 	}
214645039663SJohn Forte 
214745039663SJohn Forte err:
214845039663SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
214945039663SJohn Forte 	return (ret);
215045039663SJohn Forte }
215145039663SJohn Forte 
215245039663SJohn Forte 
2153fcf3ce44SJohn Forte typedef struct {
2154fcf3ce44SJohn Forte 	void	*bp;	/* back pointer from internal struct to main struct */
2155fcf3ce44SJohn Forte 	int	alloc_size;
2156fcf3ce44SJohn Forte } __istmf_t;
2157fcf3ce44SJohn Forte 
2158fcf3ce44SJohn Forte typedef struct {
2159fcf3ce44SJohn Forte 	__istmf_t	*fp;	/* Framework private */
2160fcf3ce44SJohn Forte 	void		*cp;	/* Caller private */
2161fcf3ce44SJohn Forte 	void		*ss;	/* struct specific */
2162fcf3ce44SJohn Forte } __stmf_t;
2163fcf3ce44SJohn Forte 
2164fcf3ce44SJohn Forte static struct {
2165fcf3ce44SJohn Forte 	int shared;
2166fcf3ce44SJohn Forte 	int fw_private;
2167fcf3ce44SJohn Forte } stmf_sizes[] = { { 0, 0 },
2168fcf3ce44SJohn Forte 	{ GET_STRUCT_SIZE(stmf_lu_provider_t),
2169fcf3ce44SJohn Forte 		GET_STRUCT_SIZE(stmf_i_lu_provider_t) },
2170fcf3ce44SJohn Forte 	{ GET_STRUCT_SIZE(stmf_port_provider_t),
2171fcf3ce44SJohn Forte 		GET_STRUCT_SIZE(stmf_i_port_provider_t) },
2172fcf3ce44SJohn Forte 	{ GET_STRUCT_SIZE(stmf_local_port_t),
2173fcf3ce44SJohn Forte 		GET_STRUCT_SIZE(stmf_i_local_port_t) },
2174fcf3ce44SJohn Forte 	{ GET_STRUCT_SIZE(stmf_lu_t),
2175fcf3ce44SJohn Forte 		GET_STRUCT_SIZE(stmf_i_lu_t) },
2176fcf3ce44SJohn Forte 	{ GET_STRUCT_SIZE(stmf_scsi_session_t),
2177fcf3ce44SJohn Forte 		GET_STRUCT_SIZE(stmf_i_scsi_session_t) },
2178fcf3ce44SJohn Forte 	{ GET_STRUCT_SIZE(scsi_task_t),
2179fcf3ce44SJohn Forte 		GET_STRUCT_SIZE(stmf_i_scsi_task_t) },
2180fcf3ce44SJohn Forte 	{ GET_STRUCT_SIZE(stmf_data_buf_t),
2181fcf3ce44SJohn Forte 		GET_STRUCT_SIZE(__istmf_t) },
2182fcf3ce44SJohn Forte 	{ GET_STRUCT_SIZE(stmf_dbuf_store_t),
2183fcf3ce44SJohn Forte 		GET_STRUCT_SIZE(__istmf_t) }
2184fcf3ce44SJohn Forte 
2185fcf3ce44SJohn Forte };
2186fcf3ce44SJohn Forte 
2187fcf3ce44SJohn Forte void *
stmf_alloc(stmf_struct_id_t struct_id,int additional_size,int flags)2188fcf3ce44SJohn Forte stmf_alloc(stmf_struct_id_t struct_id, int additional_size, int flags)
2189fcf3ce44SJohn Forte {
2190fcf3ce44SJohn Forte 	int stmf_size;
2191fcf3ce44SJohn Forte 	int kmem_flag;
2192fcf3ce44SJohn Forte 	__stmf_t *sh;
2193fcf3ce44SJohn Forte 
2194fcf3ce44SJohn Forte 	if ((struct_id == 0) || (struct_id >= STMF_MAX_STRUCT_IDS))
2195fcf3ce44SJohn Forte 		return (NULL);
2196fcf3ce44SJohn Forte 
2197fcf3ce44SJohn Forte 	if ((curthread->t_flag & T_INTR_THREAD) || (flags & AF_FORCE_NOSLEEP)) {
2198fcf3ce44SJohn Forte 		kmem_flag = KM_NOSLEEP;
2199fcf3ce44SJohn Forte 	} else {
2200fcf3ce44SJohn Forte 		kmem_flag = KM_SLEEP;
2201fcf3ce44SJohn Forte 	}
2202fcf3ce44SJohn Forte 
2203fcf3ce44SJohn Forte 	additional_size = (additional_size + 7) & (~7);
2204fcf3ce44SJohn Forte 	stmf_size = stmf_sizes[struct_id].shared +
2205fcf3ce44SJohn Forte 	    stmf_sizes[struct_id].fw_private + additional_size;
2206fcf3ce44SJohn Forte 
22073fb517f7SJames Moore 	if (flags & AF_DONTZERO)
22083fb517f7SJames Moore 		sh = (__stmf_t *)kmem_alloc(stmf_size, kmem_flag);
22093fb517f7SJames Moore 	else
2210fcf3ce44SJohn Forte 		sh = (__stmf_t *)kmem_zalloc(stmf_size, kmem_flag);
2211fcf3ce44SJohn Forte 
2212fcf3ce44SJohn Forte 	if (sh == NULL)
2213fcf3ce44SJohn Forte 		return (NULL);
2214fcf3ce44SJohn Forte 
22152a8164dfSZhong Wang 	/*
22162a8164dfSZhong Wang 	 * In principle, the implementation inside stmf_alloc should not
22172a8164dfSZhong Wang 	 * be changed anyway. But the original order of framework private
22182a8164dfSZhong Wang 	 * data and caller private data does not support sglist in the caller
22192a8164dfSZhong Wang 	 * private data.
22202a8164dfSZhong Wang 	 * To work around this, the memory segments of framework private
22212a8164dfSZhong Wang 	 * data and caller private data are re-ordered here.
22222a8164dfSZhong Wang 	 * A better solution is to provide a specific interface to allocate
22232a8164dfSZhong Wang 	 * the sglist, then we will not need this workaround any more.
22242a8164dfSZhong Wang 	 * But before the new interface is available, the memory segment
22252a8164dfSZhong Wang 	 * ordering should be kept as is.
22262a8164dfSZhong Wang 	 */
22272a8164dfSZhong Wang 	sh->cp = GET_BYTE_OFFSET(sh, stmf_sizes[struct_id].shared);
22282a8164dfSZhong Wang 	sh->fp = (__istmf_t *)GET_BYTE_OFFSET(sh,
22292a8164dfSZhong Wang 	    stmf_sizes[struct_id].shared + additional_size);
2230fcf3ce44SJohn Forte 
2231fcf3ce44SJohn Forte 	sh->fp->bp = sh;
2232fcf3ce44SJohn Forte 	/* Just store the total size instead of storing additional size */
2233fcf3ce44SJohn Forte 	sh->fp->alloc_size = stmf_size;
2234fcf3ce44SJohn Forte 
2235fcf3ce44SJohn Forte 	return (sh);
2236fcf3ce44SJohn Forte }
2237fcf3ce44SJohn Forte 
2238fcf3ce44SJohn Forte void
stmf_free(void * ptr)2239fcf3ce44SJohn Forte stmf_free(void *ptr)
2240fcf3ce44SJohn Forte {
2241fcf3ce44SJohn Forte 	__stmf_t *sh = (__stmf_t *)ptr;
2242fcf3ce44SJohn Forte 
2243fcf3ce44SJohn Forte 	/*
2244fcf3ce44SJohn Forte 	 * So far we dont need any struct specific processing. If such
2245fcf3ce44SJohn Forte 	 * a need ever arises, then store the struct id in the framework
2246fcf3ce44SJohn Forte 	 * private section and get it here as sh->fp->struct_id.
2247fcf3ce44SJohn Forte 	 */
2248fcf3ce44SJohn Forte 	kmem_free(ptr, sh->fp->alloc_size);
2249fcf3ce44SJohn Forte }
2250fcf3ce44SJohn Forte 
2251fcf3ce44SJohn Forte /*
2252fcf3ce44SJohn Forte  * Given a pointer to stmf_lu_t, verifies if this lu is registered with the
2253fcf3ce44SJohn Forte  * framework and returns a pointer to framework private data for the lu.
2254fcf3ce44SJohn Forte  * Returns NULL if the lu was not found.
2255fcf3ce44SJohn Forte  */
2256fcf3ce44SJohn Forte stmf_i_lu_t *
stmf_lookup_lu(stmf_lu_t * lu)2257fcf3ce44SJohn Forte stmf_lookup_lu(stmf_lu_t *lu)
2258fcf3ce44SJohn Forte {
2259fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
2260fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
2261fcf3ce44SJohn Forte 
2262fcf3ce44SJohn Forte 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
2263fcf3ce44SJohn Forte 		if (ilu->ilu_lu == lu)
2264fcf3ce44SJohn Forte 			return (ilu);
2265fcf3ce44SJohn Forte 	}
2266fcf3ce44SJohn Forte 	return (NULL);
2267fcf3ce44SJohn Forte }
2268fcf3ce44SJohn Forte 
2269fcf3ce44SJohn Forte /*
22701b7fc709Stim szeto  * Given a pointer to stmf_local_port_t, verifies if this lport is registered
22711b7fc709Stim szeto  * with the framework and returns a pointer to framework private data for
22721b7fc709Stim szeto  * the lport.
22731b7fc709Stim szeto  * Returns NULL if the lport was not found.
2274fcf3ce44SJohn Forte  */
2275fcf3ce44SJohn Forte stmf_i_local_port_t *
stmf_lookup_lport(stmf_local_port_t * lport)2276fcf3ce44SJohn Forte stmf_lookup_lport(stmf_local_port_t *lport)
2277fcf3ce44SJohn Forte {
2278fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
2279fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
2280fcf3ce44SJohn Forte 
2281fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
2282fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
2283fcf3ce44SJohn Forte 		if (ilport->ilport_lport == lport)
2284fcf3ce44SJohn Forte 			return (ilport);
2285fcf3ce44SJohn Forte 	}
2286fcf3ce44SJohn Forte 	return (NULL);
2287fcf3ce44SJohn Forte }
2288fcf3ce44SJohn Forte 
2289fcf3ce44SJohn Forte stmf_status_t
stmf_register_lu_provider(stmf_lu_provider_t * lp)2290fcf3ce44SJohn Forte stmf_register_lu_provider(stmf_lu_provider_t *lp)
2291fcf3ce44SJohn Forte {
2292fcf3ce44SJohn Forte 	stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private;
2293fcf3ce44SJohn Forte 	stmf_pp_data_t *ppd;
2294fcf3ce44SJohn Forte 	uint32_t cb_flags;
2295fcf3ce44SJohn Forte 
229645039663SJohn Forte 	if (lp->lp_lpif_rev != LPIF_REV_1 && lp->lp_lpif_rev != LPIF_REV_2)
2297fcf3ce44SJohn Forte 		return (STMF_FAILURE);
2298fcf3ce44SJohn Forte 
2299fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
2300fcf3ce44SJohn Forte 	ilp->ilp_next = stmf_state.stmf_ilplist;
2301fcf3ce44SJohn Forte 	stmf_state.stmf_ilplist = ilp;
2302fcf3ce44SJohn Forte 	stmf_state.stmf_nlps++;
2303fcf3ce44SJohn Forte 
2304fcf3ce44SJohn Forte 	/* See if we need to do a callback */
2305fcf3ce44SJohn Forte 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2306fcf3ce44SJohn Forte 		if (strcmp(ppd->ppd_name, lp->lp_name) == 0) {
2307fcf3ce44SJohn Forte 			break;
2308fcf3ce44SJohn Forte 		}
2309fcf3ce44SJohn Forte 	}
2310fcf3ce44SJohn Forte 	if ((ppd == NULL) || (ppd->ppd_nv == NULL)) {
2311fcf3ce44SJohn Forte 		goto rlp_bail_out;
2312fcf3ce44SJohn Forte 	}
2313fcf3ce44SJohn Forte 	ilp->ilp_ppd = ppd;
2314fcf3ce44SJohn Forte 	ppd->ppd_provider = ilp;
2315fcf3ce44SJohn Forte 	if (lp->lp_cb == NULL)
2316fcf3ce44SJohn Forte 		goto rlp_bail_out;
2317fcf3ce44SJohn Forte 	ilp->ilp_cb_in_progress = 1;
2318fcf3ce44SJohn Forte 	cb_flags = STMF_PCB_PREG_COMPLETE;
2319fcf3ce44SJohn Forte 	if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
2320fcf3ce44SJohn Forte 		cb_flags |= STMF_PCB_STMF_ONLINING;
2321fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
2322fcf3ce44SJohn Forte 	lp->lp_cb(lp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2323fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
2324fcf3ce44SJohn Forte 	ilp->ilp_cb_in_progress = 0;
2325fcf3ce44SJohn Forte 
2326fcf3ce44SJohn Forte rlp_bail_out:
2327fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
2328fcf3ce44SJohn Forte 
2329fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
2330fcf3ce44SJohn Forte }
2331fcf3ce44SJohn Forte 
2332fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_lu_provider(stmf_lu_provider_t * lp)2333fcf3ce44SJohn Forte stmf_deregister_lu_provider(stmf_lu_provider_t *lp)
2334fcf3ce44SJohn Forte {
2335fcf3ce44SJohn Forte 	stmf_i_lu_provider_t	**ppilp;
2336fcf3ce44SJohn Forte 	stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private;
2337fcf3ce44SJohn Forte 
2338fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
2339fcf3ce44SJohn Forte 	if (ilp->ilp_nlus || ilp->ilp_cb_in_progress) {
2340fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
2341fcf3ce44SJohn Forte 		return (STMF_BUSY);
2342fcf3ce44SJohn Forte 	}
2343fcf3ce44SJohn Forte 	for (ppilp = &stmf_state.stmf_ilplist; *ppilp != NULL;
2344fcf3ce44SJohn Forte 	    ppilp = &((*ppilp)->ilp_next)) {
2345fcf3ce44SJohn Forte 		if (*ppilp == ilp) {
2346fcf3ce44SJohn Forte 			*ppilp = ilp->ilp_next;
2347fcf3ce44SJohn Forte 			stmf_state.stmf_nlps--;
2348fcf3ce44SJohn Forte 			if (ilp->ilp_ppd) {
2349fcf3ce44SJohn Forte 				ilp->ilp_ppd->ppd_provider = NULL;
2350fcf3ce44SJohn Forte 				ilp->ilp_ppd = NULL;
2351fcf3ce44SJohn Forte 			}
2352fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
2353fcf3ce44SJohn Forte 			return (STMF_SUCCESS);
2354fcf3ce44SJohn Forte 		}
2355fcf3ce44SJohn Forte 	}
2356fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
2357fcf3ce44SJohn Forte 	return (STMF_NOT_FOUND);
2358fcf3ce44SJohn Forte }
2359fcf3ce44SJohn Forte 
2360fcf3ce44SJohn Forte stmf_status_t
stmf_register_port_provider(stmf_port_provider_t * pp)2361fcf3ce44SJohn Forte stmf_register_port_provider(stmf_port_provider_t *pp)
2362fcf3ce44SJohn Forte {
2363fcf3ce44SJohn Forte 	stmf_i_port_provider_t *ipp =
2364fcf3ce44SJohn Forte 	    (stmf_i_port_provider_t *)pp->pp_stmf_private;
2365fcf3ce44SJohn Forte 	stmf_pp_data_t *ppd;
2366fcf3ce44SJohn Forte 	uint32_t cb_flags;
2367fcf3ce44SJohn Forte 
2368fcf3ce44SJohn Forte 	if (pp->pp_portif_rev != PORTIF_REV_1)
2369fcf3ce44SJohn Forte 		return (STMF_FAILURE);
2370fcf3ce44SJohn Forte 
2371fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
2372fcf3ce44SJohn Forte 	ipp->ipp_next = stmf_state.stmf_ipplist;
2373fcf3ce44SJohn Forte 	stmf_state.stmf_ipplist = ipp;
2374fcf3ce44SJohn Forte 	stmf_state.stmf_npps++;
2375fcf3ce44SJohn Forte 	/* See if we need to do a callback */
2376fcf3ce44SJohn Forte 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2377fcf3ce44SJohn Forte 		if (strcmp(ppd->ppd_name, pp->pp_name) == 0) {
2378fcf3ce44SJohn Forte 			break;
2379fcf3ce44SJohn Forte 		}
2380fcf3ce44SJohn Forte 	}
2381fcf3ce44SJohn Forte 	if ((ppd == NULL) || (ppd->ppd_nv == NULL)) {
2382fcf3ce44SJohn Forte 		goto rpp_bail_out;
2383fcf3ce44SJohn Forte 	}
2384fcf3ce44SJohn Forte 	ipp->ipp_ppd = ppd;
2385fcf3ce44SJohn Forte 	ppd->ppd_provider = ipp;
2386fcf3ce44SJohn Forte 	if (pp->pp_cb == NULL)
2387fcf3ce44SJohn Forte 		goto rpp_bail_out;
2388fcf3ce44SJohn Forte 	ipp->ipp_cb_in_progress = 1;
2389fcf3ce44SJohn Forte 	cb_flags = STMF_PCB_PREG_COMPLETE;
2390fcf3ce44SJohn Forte 	if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
2391fcf3ce44SJohn Forte 		cb_flags |= STMF_PCB_STMF_ONLINING;
2392fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
2393fcf3ce44SJohn Forte 	pp->pp_cb(pp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2394fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
2395fcf3ce44SJohn Forte 	ipp->ipp_cb_in_progress = 0;
2396fcf3ce44SJohn Forte 
2397fcf3ce44SJohn Forte rpp_bail_out:
2398fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
2399fcf3ce44SJohn Forte 
2400fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
2401fcf3ce44SJohn Forte }
2402fcf3ce44SJohn Forte 
2403fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_port_provider(stmf_port_provider_t * pp)2404fcf3ce44SJohn Forte stmf_deregister_port_provider(stmf_port_provider_t *pp)
2405fcf3ce44SJohn Forte {
2406fcf3ce44SJohn Forte 	stmf_i_port_provider_t *ipp =
2407fcf3ce44SJohn Forte 	    (stmf_i_port_provider_t *)pp->pp_stmf_private;
2408fcf3ce44SJohn Forte 	stmf_i_port_provider_t **ppipp;
2409fcf3ce44SJohn Forte 
2410fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
2411fcf3ce44SJohn Forte 	if (ipp->ipp_npps || ipp->ipp_cb_in_progress) {
2412fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
2413fcf3ce44SJohn Forte 		return (STMF_BUSY);
2414fcf3ce44SJohn Forte 	}
2415fcf3ce44SJohn Forte 	for (ppipp = &stmf_state.stmf_ipplist; *ppipp != NULL;
2416fcf3ce44SJohn Forte 	    ppipp = &((*ppipp)->ipp_next)) {
2417fcf3ce44SJohn Forte 		if (*ppipp == ipp) {
2418fcf3ce44SJohn Forte 			*ppipp = ipp->ipp_next;
2419fcf3ce44SJohn Forte 			stmf_state.stmf_npps--;
2420fcf3ce44SJohn Forte 			if (ipp->ipp_ppd) {
2421fcf3ce44SJohn Forte 				ipp->ipp_ppd->ppd_provider = NULL;
2422fcf3ce44SJohn Forte 				ipp->ipp_ppd = NULL;
2423fcf3ce44SJohn Forte 			}
2424fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
2425fcf3ce44SJohn Forte 			return (STMF_SUCCESS);
2426fcf3ce44SJohn Forte 		}
2427fcf3ce44SJohn Forte 	}
2428fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
2429fcf3ce44SJohn Forte 	return (STMF_NOT_FOUND);
2430fcf3ce44SJohn Forte }
2431fcf3ce44SJohn Forte 
2432fcf3ce44SJohn Forte int
stmf_load_ppd_ioctl(stmf_ppioctl_data_t * ppi,uint64_t * ppi_token,uint32_t * err_ret)24338fe96085Stim szeto stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
24348fe96085Stim szeto     uint32_t *err_ret)
2435fcf3ce44SJohn Forte {
2436fcf3ce44SJohn Forte 	stmf_i_port_provider_t		*ipp;
2437fcf3ce44SJohn Forte 	stmf_i_lu_provider_t		*ilp;
2438fcf3ce44SJohn Forte 	stmf_pp_data_t			*ppd;
2439fcf3ce44SJohn Forte 	nvlist_t			*nv;
2440fcf3ce44SJohn Forte 	int				s;
2441fcf3ce44SJohn Forte 	int				ret;
2442fcf3ce44SJohn Forte 
24438fe96085Stim szeto 	*err_ret = 0;
24448fe96085Stim szeto 
2445fcf3ce44SJohn Forte 	if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
2446fcf3ce44SJohn Forte 		return (EINVAL);
2447fcf3ce44SJohn Forte 	}
2448fcf3ce44SJohn Forte 
2449fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
2450fcf3ce44SJohn Forte 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2451fcf3ce44SJohn Forte 		if (ppi->ppi_lu_provider) {
2452fcf3ce44SJohn Forte 			if (!ppd->ppd_lu_provider)
2453fcf3ce44SJohn Forte 				continue;
2454fcf3ce44SJohn Forte 		} else if (ppi->ppi_port_provider) {
2455fcf3ce44SJohn Forte 			if (!ppd->ppd_port_provider)
2456fcf3ce44SJohn Forte 				continue;
2457fcf3ce44SJohn Forte 		}
2458fcf3ce44SJohn Forte 		if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
2459fcf3ce44SJohn Forte 			break;
2460fcf3ce44SJohn Forte 	}
2461fcf3ce44SJohn Forte 
2462fcf3ce44SJohn Forte 	if (ppd == NULL) {
2463fcf3ce44SJohn Forte 		/* New provider */
2464fcf3ce44SJohn Forte 		s = strlen(ppi->ppi_name);
2465fcf3ce44SJohn Forte 		if (s > 254) {
2466fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
2467fcf3ce44SJohn Forte 			return (EINVAL);
2468fcf3ce44SJohn Forte 		}
2469fcf3ce44SJohn Forte 		s += sizeof (stmf_pp_data_t) - 7;
2470fcf3ce44SJohn Forte 
2471fcf3ce44SJohn Forte 		ppd = kmem_zalloc(s, KM_NOSLEEP);
2472fcf3ce44SJohn Forte 		if (ppd == NULL) {
2473fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
2474fcf3ce44SJohn Forte 			return (ENOMEM);
2475fcf3ce44SJohn Forte 		}
2476fcf3ce44SJohn Forte 		ppd->ppd_alloc_size = s;
2477fcf3ce44SJohn Forte 		(void) strcpy(ppd->ppd_name, ppi->ppi_name);
2478fcf3ce44SJohn Forte 
2479fcf3ce44SJohn Forte 		/* See if this provider already exists */
2480fcf3ce44SJohn Forte 		if (ppi->ppi_lu_provider) {
2481fcf3ce44SJohn Forte 			ppd->ppd_lu_provider = 1;
2482fcf3ce44SJohn Forte 			for (ilp = stmf_state.stmf_ilplist; ilp != NULL;
2483fcf3ce44SJohn Forte 			    ilp = ilp->ilp_next) {
2484fcf3ce44SJohn Forte 				if (strcmp(ppi->ppi_name,
2485fcf3ce44SJohn Forte 				    ilp->ilp_lp->lp_name) == 0) {
2486fcf3ce44SJohn Forte 					ppd->ppd_provider = ilp;
2487fcf3ce44SJohn Forte 					ilp->ilp_ppd = ppd;
2488fcf3ce44SJohn Forte 					break;
2489fcf3ce44SJohn Forte 				}
2490fcf3ce44SJohn Forte 			}
2491fcf3ce44SJohn Forte 		} else {
2492fcf3ce44SJohn Forte 			ppd->ppd_port_provider = 1;
2493fcf3ce44SJohn Forte 			for (ipp = stmf_state.stmf_ipplist; ipp != NULL;
2494fcf3ce44SJohn Forte 			    ipp = ipp->ipp_next) {
2495fcf3ce44SJohn Forte 				if (strcmp(ppi->ppi_name,
2496fcf3ce44SJohn Forte 				    ipp->ipp_pp->pp_name) == 0) {
2497fcf3ce44SJohn Forte 					ppd->ppd_provider = ipp;
2498fcf3ce44SJohn Forte 					ipp->ipp_ppd = ppd;
2499fcf3ce44SJohn Forte 					break;
2500fcf3ce44SJohn Forte 				}
2501fcf3ce44SJohn Forte 			}
2502fcf3ce44SJohn Forte 		}
2503fcf3ce44SJohn Forte 
2504fcf3ce44SJohn Forte 		/* Link this ppd in */
2505fcf3ce44SJohn Forte 		ppd->ppd_next = stmf_state.stmf_ppdlist;
2506fcf3ce44SJohn Forte 		stmf_state.stmf_ppdlist = ppd;
2507fcf3ce44SJohn Forte 	}
2508fcf3ce44SJohn Forte 
25098fe96085Stim szeto 	/*
25108fe96085Stim szeto 	 * User is requesting that the token be checked.
25118fe96085Stim szeto 	 * If there was another set after the user's get
25128fe96085Stim szeto 	 * it's an error
25138fe96085Stim szeto 	 */
25148fe96085Stim szeto 	if (ppi->ppi_token_valid) {
25158fe96085Stim szeto 		if (ppi->ppi_token != ppd->ppd_token) {
25168fe96085Stim szeto 			*err_ret = STMF_IOCERR_PPD_UPDATED;
25178fe96085Stim szeto 			mutex_exit(&stmf_state.stmf_lock);
25188fe96085Stim szeto 			return (EINVAL);
25198fe96085Stim szeto 		}
25208fe96085Stim szeto 	}
25218fe96085Stim szeto 
2522fcf3ce44SJohn Forte 	if ((ret = nvlist_unpack((char *)ppi->ppi_data,
2523fcf3ce44SJohn Forte 	    (size_t)ppi->ppi_data_size, &nv, KM_NOSLEEP)) != 0) {
2524fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
2525fcf3ce44SJohn Forte 		return (ret);
2526fcf3ce44SJohn Forte 	}
2527fcf3ce44SJohn Forte 
2528fcf3ce44SJohn Forte 	/* Free any existing lists and add this one to the ppd */
252961dfa509SRick McNeal 	if (ppd->ppd_nv)
2530fcf3ce44SJohn Forte 		nvlist_free(ppd->ppd_nv);
2531fcf3ce44SJohn Forte 	ppd->ppd_nv = nv;
2532fcf3ce44SJohn Forte 
25338fe96085Stim szeto 	/* set the token for writes */
25348fe96085Stim szeto 	ppd->ppd_token++;
25358fe96085Stim szeto 	/* return token to caller */
25368fe96085Stim szeto 	if (ppi_token) {
25378fe96085Stim szeto 		*ppi_token = ppd->ppd_token;
25388fe96085Stim szeto 	}
25398fe96085Stim szeto 
2540fcf3ce44SJohn Forte 	/* If there is a provider registered, do the notifications */
2541fcf3ce44SJohn Forte 	if (ppd->ppd_provider) {
2542fcf3ce44SJohn Forte 		uint32_t cb_flags = 0;
2543fcf3ce44SJohn Forte 
2544fcf3ce44SJohn Forte 		if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
2545fcf3ce44SJohn Forte 			cb_flags |= STMF_PCB_STMF_ONLINING;
2546fcf3ce44SJohn Forte 		if (ppi->ppi_lu_provider) {
2547fcf3ce44SJohn Forte 			ilp = (stmf_i_lu_provider_t *)ppd->ppd_provider;
2548fcf3ce44SJohn Forte 			if (ilp->ilp_lp->lp_cb == NULL)
2549fcf3ce44SJohn Forte 				goto bail_out;
2550fcf3ce44SJohn Forte 			ilp->ilp_cb_in_progress = 1;
2551fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
2552fcf3ce44SJohn Forte 			ilp->ilp_lp->lp_cb(ilp->ilp_lp,
2553fcf3ce44SJohn Forte 			    STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2554fcf3ce44SJohn Forte 			mutex_enter(&stmf_state.stmf_lock);
2555fcf3ce44SJohn Forte 			ilp->ilp_cb_in_progress = 0;
2556fcf3ce44SJohn Forte 		} else {
2557fcf3ce44SJohn Forte 			ipp = (stmf_i_port_provider_t *)ppd->ppd_provider;
2558fcf3ce44SJohn Forte 			if (ipp->ipp_pp->pp_cb == NULL)
2559fcf3ce44SJohn Forte 				goto bail_out;
2560fcf3ce44SJohn Forte 			ipp->ipp_cb_in_progress = 1;
2561fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
2562fcf3ce44SJohn Forte 			ipp->ipp_pp->pp_cb(ipp->ipp_pp,
2563fcf3ce44SJohn Forte 			    STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2564fcf3ce44SJohn Forte 			mutex_enter(&stmf_state.stmf_lock);
2565fcf3ce44SJohn Forte 			ipp->ipp_cb_in_progress = 0;
2566fcf3ce44SJohn Forte 		}
2567fcf3ce44SJohn Forte 	}
2568fcf3ce44SJohn Forte 
2569fcf3ce44SJohn Forte bail_out:
2570fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
2571fcf3ce44SJohn Forte 
2572fcf3ce44SJohn Forte 	return (0);
2573fcf3ce44SJohn Forte }
2574fcf3ce44SJohn Forte 
2575fcf3ce44SJohn Forte void
stmf_delete_ppd(stmf_pp_data_t * ppd)2576fcf3ce44SJohn Forte stmf_delete_ppd(stmf_pp_data_t *ppd)
2577fcf3ce44SJohn Forte {
2578fcf3ce44SJohn Forte 	stmf_pp_data_t **pppd;
2579fcf3ce44SJohn Forte 
2580fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
2581fcf3ce44SJohn Forte 	if (ppd->ppd_provider) {
2582fcf3ce44SJohn Forte 		if (ppd->ppd_lu_provider) {
2583fcf3ce44SJohn Forte 			((stmf_i_lu_provider_t *)
2584fcf3ce44SJohn Forte 			    ppd->ppd_provider)->ilp_ppd = NULL;
2585fcf3ce44SJohn Forte 		} else {
2586fcf3ce44SJohn Forte 			((stmf_i_port_provider_t *)
2587fcf3ce44SJohn Forte 			    ppd->ppd_provider)->ipp_ppd = NULL;
2588fcf3ce44SJohn Forte 		}
2589fcf3ce44SJohn Forte 		ppd->ppd_provider = NULL;
2590fcf3ce44SJohn Forte 	}
2591fcf3ce44SJohn Forte 
2592fcf3ce44SJohn Forte 	for (pppd = &stmf_state.stmf_ppdlist; *pppd != NULL;
2593fcf3ce44SJohn Forte 	    pppd = &((*pppd)->ppd_next)) {
2594fcf3ce44SJohn Forte 		if (*pppd == ppd)
2595fcf3ce44SJohn Forte 			break;
2596fcf3ce44SJohn Forte 	}
2597fcf3ce44SJohn Forte 
2598fcf3ce44SJohn Forte 	if (*pppd == NULL)
2599fcf3ce44SJohn Forte 		return;
2600fcf3ce44SJohn Forte 
2601fcf3ce44SJohn Forte 	*pppd = ppd->ppd_next;
260261dfa509SRick McNeal 	if (ppd->ppd_nv)
2603fcf3ce44SJohn Forte 		nvlist_free(ppd->ppd_nv);
2604fcf3ce44SJohn Forte 
2605fcf3ce44SJohn Forte 	kmem_free(ppd, ppd->ppd_alloc_size);
2606fcf3ce44SJohn Forte }
2607fcf3ce44SJohn Forte 
2608fcf3ce44SJohn Forte int
stmf_delete_ppd_ioctl(stmf_ppioctl_data_t * ppi)2609fcf3ce44SJohn Forte stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi)
2610fcf3ce44SJohn Forte {
2611fcf3ce44SJohn Forte 	stmf_pp_data_t *ppd;
2612fcf3ce44SJohn Forte 	int ret = ENOENT;
2613fcf3ce44SJohn Forte 
2614fcf3ce44SJohn Forte 	if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
2615fcf3ce44SJohn Forte 		return (EINVAL);
2616fcf3ce44SJohn Forte 	}
2617fcf3ce44SJohn Forte 
2618fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
2619fcf3ce44SJohn Forte 
2620fcf3ce44SJohn Forte 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2621fcf3ce44SJohn Forte 		if (ppi->ppi_lu_provider) {
2622fcf3ce44SJohn Forte 			if (!ppd->ppd_lu_provider)
2623fcf3ce44SJohn Forte 				continue;
2624fcf3ce44SJohn Forte 		} else if (ppi->ppi_port_provider) {
2625fcf3ce44SJohn Forte 			if (!ppd->ppd_port_provider)
2626fcf3ce44SJohn Forte 				continue;
2627fcf3ce44SJohn Forte 		}
2628fcf3ce44SJohn Forte 		if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
2629fcf3ce44SJohn Forte 			break;
2630fcf3ce44SJohn Forte 	}
2631fcf3ce44SJohn Forte 
2632fcf3ce44SJohn Forte 	if (ppd) {
2633fcf3ce44SJohn Forte 		ret = 0;
2634fcf3ce44SJohn Forte 		stmf_delete_ppd(ppd);
2635fcf3ce44SJohn Forte 	}
2636fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
2637fcf3ce44SJohn Forte 
2638fcf3ce44SJohn Forte 	return (ret);
2639fcf3ce44SJohn Forte }
2640fcf3ce44SJohn Forte 
26418fe96085Stim szeto int
stmf_get_ppd_ioctl(stmf_ppioctl_data_t * ppi,stmf_ppioctl_data_t * ppi_out,uint32_t * err_ret)26428fe96085Stim szeto stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
26438fe96085Stim szeto     uint32_t *err_ret)
26448fe96085Stim szeto {
26458fe96085Stim szeto 	stmf_pp_data_t *ppd;
26468fe96085Stim szeto 	size_t req_size;
26478fe96085Stim szeto 	int ret = ENOENT;
26488fe96085Stim szeto 	char *bufp = (char *)ppi_out->ppi_data;
26498fe96085Stim szeto 
26508fe96085Stim szeto 	if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
26518fe96085Stim szeto 		return (EINVAL);
26528fe96085Stim szeto 	}
26538fe96085Stim szeto 
26548fe96085Stim szeto 	mutex_enter(&stmf_state.stmf_lock);
26558fe96085Stim szeto 
26568fe96085Stim szeto 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
26578fe96085Stim szeto 		if (ppi->ppi_lu_provider) {
26588fe96085Stim szeto 			if (!ppd->ppd_lu_provider)
26598fe96085Stim szeto 				continue;
26608fe96085Stim szeto 		} else if (ppi->ppi_port_provider) {
26618fe96085Stim szeto 			if (!ppd->ppd_port_provider)
26628fe96085Stim szeto 				continue;
26638fe96085Stim szeto 		}
26648fe96085Stim szeto 		if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
26658fe96085Stim szeto 			break;
26668fe96085Stim szeto 	}
26678fe96085Stim szeto 
26688fe96085Stim szeto 	if (ppd && ppd->ppd_nv) {
26698fe96085Stim szeto 		ppi_out->ppi_token = ppd->ppd_token;
26708fe96085Stim szeto 		if ((ret = nvlist_size(ppd->ppd_nv, &req_size,
26718fe96085Stim szeto 		    NV_ENCODE_XDR)) != 0) {
26728fe96085Stim szeto 			goto done;
26738fe96085Stim szeto 		}
26748fe96085Stim szeto 		ppi_out->ppi_data_size = req_size;
26758fe96085Stim szeto 		if (req_size > ppi->ppi_data_size) {
26768fe96085Stim szeto 			*err_ret = STMF_IOCERR_INSUFFICIENT_BUF;
26778fe96085Stim szeto 			ret = EINVAL;
26788fe96085Stim szeto 			goto done;
26798fe96085Stim szeto 		}
26808fe96085Stim szeto 
26818fe96085Stim szeto 		if ((ret = nvlist_pack(ppd->ppd_nv, &bufp, &req_size,
26828fe96085Stim szeto 		    NV_ENCODE_XDR, 0)) != 0) {
26838fe96085Stim szeto 			goto done;
26848fe96085Stim szeto 		}
26858fe96085Stim szeto 		ret = 0;
26868fe96085Stim szeto 	}
26878fe96085Stim szeto 
26888fe96085Stim szeto done:
26898fe96085Stim szeto 	mutex_exit(&stmf_state.stmf_lock);
26908fe96085Stim szeto 
26918fe96085Stim szeto 	return (ret);
26928fe96085Stim szeto }
26938fe96085Stim szeto 
2694fcf3ce44SJohn Forte void
stmf_delete_all_ppds()2695fcf3ce44SJohn Forte stmf_delete_all_ppds()
2696fcf3ce44SJohn Forte {
2697fcf3ce44SJohn Forte 	stmf_pp_data_t *ppd, *nppd;
2698fcf3ce44SJohn Forte 
2699fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
2700fcf3ce44SJohn Forte 	for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = nppd) {
2701fcf3ce44SJohn Forte 		nppd = ppd->ppd_next;
2702fcf3ce44SJohn Forte 		stmf_delete_ppd(ppd);
2703fcf3ce44SJohn Forte 	}
2704fcf3ce44SJohn Forte }
2705fcf3ce44SJohn Forte 
2706034d83c4Stim szeto /*
2707034d83c4Stim szeto  * 16 is the max string length of a protocol_ident, increase
2708034d83c4Stim szeto  * the size if needed.
2709034d83c4Stim szeto  */
2710034d83c4Stim szeto #define	STMF_KSTAT_LU_SZ	(STMF_GUID_INPUT + 1 + 256)
2711034d83c4Stim szeto #define	STMF_KSTAT_TGT_SZ	(256 * 2 + 16)
271261dfa509SRick McNeal #define	STMF_KSTAT_RPORT_DATAMAX	(sizeof (stmf_kstat_rport_info_t) / \
271361dfa509SRick McNeal 					    sizeof (kstat_named_t))
2714034d83c4Stim szeto 
2715034d83c4Stim szeto /*
2716034d83c4Stim szeto  * This array matches the Protocol Identifier in stmf_ioctl.h
2717034d83c4Stim szeto  */
2718427fcaf8Stim szeto #define	MAX_PROTO_STR_LEN	32
2719427fcaf8Stim szeto 
2720034d83c4Stim szeto char *protocol_ident[PROTOCOL_ANY] = {
2721034d83c4Stim szeto 	"Fibre Channel",
2722034d83c4Stim szeto 	"Parallel SCSI",
2723034d83c4Stim szeto 	"SSA",
2724034d83c4Stim szeto 	"IEEE_1394",
2725034d83c4Stim szeto 	"SRP",
2726034d83c4Stim szeto 	"iSCSI",
2727034d83c4Stim szeto 	"SAS",
2728034d83c4Stim szeto 	"ADT",
2729034d83c4Stim szeto 	"ATAPI",
2730034d83c4Stim szeto 	"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"
2731034d83c4Stim szeto };
2732034d83c4Stim szeto 
2733034d83c4Stim szeto /*
2734034d83c4Stim szeto  * Update the lun wait/run queue count
2735034d83c4Stim szeto  */
2736034d83c4Stim szeto static void
stmf_update_kstat_lu_q(scsi_task_t * task,void func ())2737034d83c4Stim szeto stmf_update_kstat_lu_q(scsi_task_t *task, void func())
2738034d83c4Stim szeto {
2739034d83c4Stim szeto 	stmf_i_lu_t		*ilu;
2740034d83c4Stim szeto 	kstat_io_t		*kip;
2741034d83c4Stim szeto 
2742034d83c4Stim szeto 	if (task->task_lu == dlun0)
2743034d83c4Stim szeto 		return;
2744034d83c4Stim szeto 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
2745034d83c4Stim szeto 	if (ilu != NULL && ilu->ilu_kstat_io != NULL) {
2746034d83c4Stim szeto 		kip = KSTAT_IO_PTR(ilu->ilu_kstat_io);
2747034d83c4Stim szeto 		if (kip != NULL) {
2748034d83c4Stim szeto 			func(kip);
2749034d83c4Stim szeto 		}
2750034d83c4Stim szeto 	}
2751034d83c4Stim szeto }
2752034d83c4Stim szeto 
2753034d83c4Stim szeto /*
2754034d83c4Stim szeto  * Update the target(lport) wait/run queue count
2755034d83c4Stim szeto  */
2756034d83c4Stim szeto static void
stmf_update_kstat_lport_q(scsi_task_t * task,void func ())2757034d83c4Stim szeto stmf_update_kstat_lport_q(scsi_task_t *task, void func())
2758034d83c4Stim szeto {
2759034d83c4Stim szeto 	stmf_i_local_port_t	*ilp;
2760034d83c4Stim szeto 	kstat_io_t		*kip;
2761034d83c4Stim szeto 
2762034d83c4Stim szeto 	ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
2763034d83c4Stim szeto 	if (ilp != NULL && ilp->ilport_kstat_io != NULL) {
2764034d83c4Stim szeto 		kip = KSTAT_IO_PTR(ilp->ilport_kstat_io);
2765034d83c4Stim szeto 		if (kip != NULL) {
2766034d83c4Stim szeto 			mutex_enter(ilp->ilport_kstat_io->ks_lock);
2767034d83c4Stim szeto 			func(kip);
2768034d83c4Stim szeto 			mutex_exit(ilp->ilport_kstat_io->ks_lock);
2769034d83c4Stim szeto 		}
2770034d83c4Stim szeto 	}
2771034d83c4Stim szeto }
2772034d83c4Stim szeto 
2773034d83c4Stim szeto static void
stmf_update_kstat_lport_io(scsi_task_t * task,stmf_data_buf_t * dbuf)2774034d83c4Stim szeto stmf_update_kstat_lport_io(scsi_task_t *task, stmf_data_buf_t *dbuf)
2775034d83c4Stim szeto {
2776034d83c4Stim szeto 	stmf_i_local_port_t	*ilp;
2777034d83c4Stim szeto 	kstat_io_t		*kip;
2778034d83c4Stim szeto 
2779034d83c4Stim szeto 	ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
2780034d83c4Stim szeto 	if (ilp != NULL && ilp->ilport_kstat_io != NULL) {
2781034d83c4Stim szeto 		kip = KSTAT_IO_PTR(ilp->ilport_kstat_io);
2782034d83c4Stim szeto 		if (kip != NULL) {
2783034d83c4Stim szeto 			mutex_enter(ilp->ilport_kstat_io->ks_lock);
2784034d83c4Stim szeto 			STMF_UPDATE_KSTAT_IO(kip, dbuf);
2785034d83c4Stim szeto 			mutex_exit(ilp->ilport_kstat_io->ks_lock);
2786034d83c4Stim szeto 		}
2787034d83c4Stim szeto 	}
2788034d83c4Stim szeto }
2789034d83c4Stim szeto 
2790034d83c4Stim szeto static void
stmf_update_kstat_rport_io(scsi_task_t * task,stmf_data_buf_t * dbuf)279161dfa509SRick McNeal stmf_update_kstat_rport_io(scsi_task_t *task, stmf_data_buf_t *dbuf)
279261dfa509SRick McNeal {
279361dfa509SRick McNeal 	stmf_i_scsi_session_t	*iss;
279461dfa509SRick McNeal 	stmf_i_remote_port_t	*irport;
279561dfa509SRick McNeal 	kstat_io_t		*kip;
279661dfa509SRick McNeal 
279761dfa509SRick McNeal 	iss = task->task_session->ss_stmf_private;
279861dfa509SRick McNeal 	irport = iss->iss_irport;
279961dfa509SRick McNeal 	if (irport->irport_kstat_io != NULL) {
280061dfa509SRick McNeal 		kip = KSTAT_IO_PTR(irport->irport_kstat_io);
280161dfa509SRick McNeal 		mutex_enter(irport->irport_kstat_io->ks_lock);
280261dfa509SRick McNeal 		STMF_UPDATE_KSTAT_IO(kip, dbuf);
280361dfa509SRick McNeal 		mutex_exit(irport->irport_kstat_io->ks_lock);
280461dfa509SRick McNeal 	}
280561dfa509SRick McNeal }
280661dfa509SRick McNeal 
280761dfa509SRick McNeal static void
stmf_update_kstat_rport_estat(scsi_task_t * task)280861dfa509SRick McNeal stmf_update_kstat_rport_estat(scsi_task_t *task)
280961dfa509SRick McNeal {
281061dfa509SRick McNeal 	stmf_i_scsi_task_t		*itask;
281161dfa509SRick McNeal 	stmf_i_scsi_session_t		*iss;
281261dfa509SRick McNeal 	stmf_i_remote_port_t		*irport;
281361dfa509SRick McNeal 	stmf_kstat_rport_estat_t	*ks_estat;
281461dfa509SRick McNeal 	hrtime_t			lat = 0;
281561dfa509SRick McNeal 	uint32_t			n = 0;
281661dfa509SRick McNeal 
281761dfa509SRick McNeal 	itask = task->task_stmf_private;
281861dfa509SRick McNeal 	iss = task->task_session->ss_stmf_private;
281961dfa509SRick McNeal 	irport = iss->iss_irport;
282061dfa509SRick McNeal 
282161dfa509SRick McNeal 	if (irport->irport_kstat_estat == NULL)
282261dfa509SRick McNeal 		return;
282361dfa509SRick McNeal 
282461dfa509SRick McNeal 	ks_estat = (stmf_kstat_rport_estat_t *)KSTAT_NAMED_PTR(
282561dfa509SRick McNeal 	    irport->irport_kstat_estat);
282661dfa509SRick McNeal 
282761dfa509SRick McNeal 	mutex_enter(irport->irport_kstat_estat->ks_lock);
282861dfa509SRick McNeal 
282961dfa509SRick McNeal 	if (task->task_flags & TF_READ_DATA)
283061dfa509SRick McNeal 		n = atomic_dec_32_nv(&irport->irport_nread_tasks);
283161dfa509SRick McNeal 	else if (task->task_flags & TF_WRITE_DATA)
283261dfa509SRick McNeal 		n = atomic_dec_32_nv(&irport->irport_nwrite_tasks);
283361dfa509SRick McNeal 
283461dfa509SRick McNeal 	if (itask->itask_read_xfer > 0) {
283561dfa509SRick McNeal 		ks_estat->i_nread_tasks.value.ui64++;
283661dfa509SRick McNeal 		lat = stmf_update_rport_timestamps(
283761dfa509SRick McNeal 		    &irport->irport_rdstart_timestamp,
283861dfa509SRick McNeal 		    &irport->irport_rddone_timestamp, itask);
283961dfa509SRick McNeal 		if (n == 0)
284061dfa509SRick McNeal 			ks_estat->i_rport_read_latency.value.ui64 += lat;
284161dfa509SRick McNeal 	} else if ((itask->itask_write_xfer > 0) ||
284261dfa509SRick McNeal 	    (task->task_flags & TF_INITIAL_BURST)) {
284361dfa509SRick McNeal 		ks_estat->i_nwrite_tasks.value.ui64++;
284461dfa509SRick McNeal 		lat = stmf_update_rport_timestamps(
284561dfa509SRick McNeal 		    &irport->irport_wrstart_timestamp,
284661dfa509SRick McNeal 		    &irport->irport_wrdone_timestamp, itask);
284761dfa509SRick McNeal 		if (n == 0)
284861dfa509SRick McNeal 			ks_estat->i_rport_write_latency.value.ui64 += lat;
284961dfa509SRick McNeal 	}
285061dfa509SRick McNeal 
285161dfa509SRick McNeal 	if (n == 0) {
285261dfa509SRick McNeal 		if (task->task_flags & TF_READ_DATA) {
285361dfa509SRick McNeal 			irport->irport_rdstart_timestamp = LLONG_MAX;
285461dfa509SRick McNeal 			irport->irport_rddone_timestamp = 0;
285561dfa509SRick McNeal 		} else if (task->task_flags & TF_WRITE_DATA) {
285661dfa509SRick McNeal 			irport->irport_wrstart_timestamp = LLONG_MAX;
285761dfa509SRick McNeal 			irport->irport_wrdone_timestamp = 0;
285861dfa509SRick McNeal 		}
285961dfa509SRick McNeal 	}
286061dfa509SRick McNeal 
286161dfa509SRick McNeal 	mutex_exit(irport->irport_kstat_estat->ks_lock);
286261dfa509SRick McNeal }
286361dfa509SRick McNeal 
286461dfa509SRick McNeal static hrtime_t
stmf_update_rport_timestamps(hrtime_t * start_tstamp,hrtime_t * done_tstamp,stmf_i_scsi_task_t * itask)286561dfa509SRick McNeal stmf_update_rport_timestamps(hrtime_t *start_tstamp, hrtime_t *done_tstamp,
286661dfa509SRick McNeal     stmf_i_scsi_task_t *itask)
286761dfa509SRick McNeal {
286861dfa509SRick McNeal 	*start_tstamp = MIN(*start_tstamp, itask->itask_start_timestamp);
286961dfa509SRick McNeal 	if ((*done_tstamp == 0) &&
287061dfa509SRick McNeal 	    (itask->itask_xfer_done_timestamp == 0)) {
287161dfa509SRick McNeal 		*done_tstamp = *start_tstamp;
287261dfa509SRick McNeal 	} else {
287361dfa509SRick McNeal 		*done_tstamp = MAX(*done_tstamp,
287461dfa509SRick McNeal 		    itask->itask_xfer_done_timestamp);
287561dfa509SRick McNeal 	}
287661dfa509SRick McNeal 
287761dfa509SRick McNeal 	return (*done_tstamp - *start_tstamp);
287861dfa509SRick McNeal }
287961dfa509SRick McNeal 
288061dfa509SRick McNeal static void
stmf_update_kstat_lu_io(scsi_task_t * task,stmf_data_buf_t * dbuf)2881034d83c4Stim szeto stmf_update_kstat_lu_io(scsi_task_t *task, stmf_data_buf_t *dbuf)
2882034d83c4Stim szeto {
2883034d83c4Stim szeto 	stmf_i_lu_t		*ilu;
2884034d83c4Stim szeto 	kstat_io_t		*kip;
2885034d83c4Stim szeto 
2886034d83c4Stim szeto 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
2887034d83c4Stim szeto 	if (ilu != NULL && ilu->ilu_kstat_io != NULL) {
2888034d83c4Stim szeto 		kip = KSTAT_IO_PTR(ilu->ilu_kstat_io);
2889034d83c4Stim szeto 		if (kip != NULL) {
2890034d83c4Stim szeto 			mutex_enter(ilu->ilu_kstat_io->ks_lock);
2891034d83c4Stim szeto 			STMF_UPDATE_KSTAT_IO(kip, dbuf);
2892034d83c4Stim szeto 			mutex_exit(ilu->ilu_kstat_io->ks_lock);
2893034d83c4Stim szeto 		}
2894034d83c4Stim szeto 	}
2895034d83c4Stim szeto }
2896034d83c4Stim szeto 
2897034d83c4Stim szeto static void
stmf_create_kstat_lu(stmf_i_lu_t * ilu)2898034d83c4Stim szeto stmf_create_kstat_lu(stmf_i_lu_t *ilu)
2899034d83c4Stim szeto {
2900034d83c4Stim szeto 	char				ks_nm[KSTAT_STRLEN];
2901034d83c4Stim szeto 	stmf_kstat_lu_info_t		*ks_lu;
2902034d83c4Stim szeto 
2903034d83c4Stim szeto 	/* create kstat lun info */
2904034d83c4Stim szeto 	ks_lu = (stmf_kstat_lu_info_t *)kmem_zalloc(STMF_KSTAT_LU_SZ,
2905034d83c4Stim szeto 	    KM_NOSLEEP);
2906034d83c4Stim szeto 	if (ks_lu == NULL) {
2907034d83c4Stim szeto 		cmn_err(CE_WARN, "STMF: kmem_zalloc failed");
2908034d83c4Stim szeto 		return;
2909034d83c4Stim szeto 	}
2910034d83c4Stim szeto 
2911034d83c4Stim szeto 	bzero(ks_nm, sizeof (ks_nm));
2912034d83c4Stim szeto 	(void) sprintf(ks_nm, "stmf_lu_%"PRIxPTR"", (uintptr_t)ilu);
2913034d83c4Stim szeto 	if ((ilu->ilu_kstat_info = kstat_create(STMF_MODULE_NAME, 0,
2914034d83c4Stim szeto 	    ks_nm, "misc", KSTAT_TYPE_NAMED,
2915034d83c4Stim szeto 	    sizeof (stmf_kstat_lu_info_t) / sizeof (kstat_named_t),
2916034d83c4Stim szeto 	    KSTAT_FLAG_VIRTUAL)) == NULL) {
2917034d83c4Stim szeto 		kmem_free(ks_lu, STMF_KSTAT_LU_SZ);
2918034d83c4Stim szeto 		cmn_err(CE_WARN, "STMF: kstat_create lu failed");
2919034d83c4Stim szeto 		return;
2920034d83c4Stim szeto 	}
2921034d83c4Stim szeto 
2922034d83c4Stim szeto 	ilu->ilu_kstat_info->ks_data_size = STMF_KSTAT_LU_SZ;
2923034d83c4Stim szeto 	ilu->ilu_kstat_info->ks_data = ks_lu;
2924034d83c4Stim szeto 
2925034d83c4Stim szeto 	kstat_named_init(&ks_lu->i_lun_guid, "lun-guid",
2926034d83c4Stim szeto 	    KSTAT_DATA_STRING);
2927034d83c4Stim szeto 	kstat_named_init(&ks_lu->i_lun_alias, "lun-alias",
2928034d83c4Stim szeto 	    KSTAT_DATA_STRING);
2929034d83c4Stim szeto 
2930034d83c4Stim szeto 	/* convert guid to hex string */
2931034d83c4Stim szeto 	int		i;
2932034d83c4Stim szeto 	uint8_t		*p = ilu->ilu_lu->lu_id->ident;
2933034d83c4Stim szeto 	bzero(ilu->ilu_ascii_hex_guid, sizeof (ilu->ilu_ascii_hex_guid));
2934034d83c4Stim szeto 	for (i = 0; i < STMF_GUID_INPUT / 2; i++) {
2935034d83c4Stim szeto 		(void) sprintf(&ilu->ilu_ascii_hex_guid[i * 2], "%02x", p[i]);
2936034d83c4Stim szeto 	}
2937034d83c4Stim szeto 	kstat_named_setstr(&ks_lu->i_lun_guid,
2938034d83c4Stim szeto 	    (const char *)ilu->ilu_ascii_hex_guid);
2939034d83c4Stim szeto 	kstat_named_setstr(&ks_lu->i_lun_alias,
2940034d83c4Stim szeto 	    (const char *)ilu->ilu_lu->lu_alias);
2941034d83c4Stim szeto 	kstat_install(ilu->ilu_kstat_info);
2942034d83c4Stim szeto 
2943034d83c4Stim szeto 	/* create kstat lun io */
2944034d83c4Stim szeto 	bzero(ks_nm, sizeof (ks_nm));
2945034d83c4Stim szeto 	(void) sprintf(ks_nm, "stmf_lu_io_%"PRIxPTR"", (uintptr_t)ilu);
2946034d83c4Stim szeto 	if ((ilu->ilu_kstat_io = kstat_create(STMF_MODULE_NAME, 0,
2947034d83c4Stim szeto 	    ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
2948034d83c4Stim szeto 		cmn_err(CE_WARN, "STMF: kstat_create lu_io failed");
2949034d83c4Stim szeto 		return;
2950034d83c4Stim szeto 	}
2951034d83c4Stim szeto 	mutex_init(&ilu->ilu_kstat_lock, NULL, MUTEX_DRIVER, 0);
2952034d83c4Stim szeto 	ilu->ilu_kstat_io->ks_lock = &ilu->ilu_kstat_lock;
2953034d83c4Stim szeto 	kstat_install(ilu->ilu_kstat_io);
2954034d83c4Stim szeto }
2955034d83c4Stim szeto 
2956034d83c4Stim szeto static void
stmf_create_kstat_lport(stmf_i_local_port_t * ilport)2957034d83c4Stim szeto stmf_create_kstat_lport(stmf_i_local_port_t *ilport)
2958034d83c4Stim szeto {
2959034d83c4Stim szeto 	char				ks_nm[KSTAT_STRLEN];
2960034d83c4Stim szeto 	stmf_kstat_tgt_info_t		*ks_tgt;
2961034d83c4Stim szeto 	int				id, len;
2962034d83c4Stim szeto 
2963034d83c4Stim szeto 	/* create kstat lport info */
2964034d83c4Stim szeto 	ks_tgt = (stmf_kstat_tgt_info_t *)kmem_zalloc(STMF_KSTAT_TGT_SZ,
2965034d83c4Stim szeto 	    KM_NOSLEEP);
2966034d83c4Stim szeto 	if (ks_tgt == NULL) {
2967034d83c4Stim szeto 		cmn_err(CE_WARN, "STMF: kmem_zalloc failed");
2968034d83c4Stim szeto 		return;
2969034d83c4Stim szeto 	}
2970034d83c4Stim szeto 
2971034d83c4Stim szeto 	bzero(ks_nm, sizeof (ks_nm));
2972034d83c4Stim szeto 	(void) sprintf(ks_nm, "stmf_tgt_%"PRIxPTR"", (uintptr_t)ilport);
2973034d83c4Stim szeto 	if ((ilport->ilport_kstat_info = kstat_create(STMF_MODULE_NAME,
2974034d83c4Stim szeto 	    0, ks_nm, "misc", KSTAT_TYPE_NAMED,
2975034d83c4Stim szeto 	    sizeof (stmf_kstat_tgt_info_t) / sizeof (kstat_named_t),
2976034d83c4Stim szeto 	    KSTAT_FLAG_VIRTUAL)) == NULL) {
2977034d83c4Stim szeto 		kmem_free(ks_tgt, STMF_KSTAT_TGT_SZ);
2978034d83c4Stim szeto 		cmn_err(CE_WARN, "STMF: kstat_create target failed");
2979034d83c4Stim szeto 		return;
2980034d83c4Stim szeto 	}
2981034d83c4Stim szeto 
2982034d83c4Stim szeto 	ilport->ilport_kstat_info->ks_data_size = STMF_KSTAT_TGT_SZ;
2983034d83c4Stim szeto 	ilport->ilport_kstat_info->ks_data = ks_tgt;
2984034d83c4Stim szeto 
2985034d83c4Stim szeto 	kstat_named_init(&ks_tgt->i_tgt_name, "target-name",
2986034d83c4Stim szeto 	    KSTAT_DATA_STRING);
2987034d83c4Stim szeto 	kstat_named_init(&ks_tgt->i_tgt_alias, "target-alias",
2988034d83c4Stim szeto 	    KSTAT_DATA_STRING);
2989034d83c4Stim szeto 	kstat_named_init(&ks_tgt->i_protocol, "protocol",
2990034d83c4Stim szeto 	    KSTAT_DATA_STRING);
2991034d83c4Stim szeto 
2992034d83c4Stim szeto 	/* ident might not be null terminated */
2993034d83c4Stim szeto 	len = ilport->ilport_lport->lport_id->ident_length;
2994034d83c4Stim szeto 	bcopy(ilport->ilport_lport->lport_id->ident,
2995034d83c4Stim szeto 	    ilport->ilport_kstat_tgt_name, len);
2996bad5e468SToomas Soome 	ilport->ilport_kstat_tgt_name[len + 1] = '\0';
2997034d83c4Stim szeto 	kstat_named_setstr(&ks_tgt->i_tgt_name,
2998034d83c4Stim szeto 	    (const char *)ilport->ilport_kstat_tgt_name);
2999034d83c4Stim szeto 	kstat_named_setstr(&ks_tgt->i_tgt_alias,
3000034d83c4Stim szeto 	    (const char *)ilport->ilport_lport->lport_alias);
3001034d83c4Stim szeto 	/* protocol */
3002034d83c4Stim szeto 	if ((id = ilport->ilport_lport->lport_id->protocol_id) > PROTOCOL_ANY) {
3003034d83c4Stim szeto 		cmn_err(CE_WARN, "STMF: protocol_id out of bound");
3004034d83c4Stim szeto 		id = PROTOCOL_ANY;
3005034d83c4Stim szeto 	}
3006034d83c4Stim szeto 	kstat_named_setstr(&ks_tgt->i_protocol, protocol_ident[id]);
3007034d83c4Stim szeto 	kstat_install(ilport->ilport_kstat_info);
3008034d83c4Stim szeto 
3009034d83c4Stim szeto 	/* create kstat lport io */
3010034d83c4Stim szeto 	bzero(ks_nm, sizeof (ks_nm));
3011034d83c4Stim szeto 	(void) sprintf(ks_nm, "stmf_tgt_io_%"PRIxPTR"", (uintptr_t)ilport);
3012034d83c4Stim szeto 	if ((ilport->ilport_kstat_io = kstat_create(STMF_MODULE_NAME, 0,
3013034d83c4Stim szeto 	    ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
3014034d83c4Stim szeto 		cmn_err(CE_WARN, "STMF: kstat_create target_io failed");
3015034d83c4Stim szeto 		return;
3016034d83c4Stim szeto 	}
3017034d83c4Stim szeto 	mutex_init(&ilport->ilport_kstat_lock, NULL, MUTEX_DRIVER, 0);
3018034d83c4Stim szeto 	ilport->ilport_kstat_io->ks_lock = &ilport->ilport_kstat_lock;
3019034d83c4Stim szeto 	kstat_install(ilport->ilport_kstat_io);
3020034d83c4Stim szeto }
3021034d83c4Stim szeto 
302245039663SJohn Forte /*
302345039663SJohn Forte  * set the asymmetric access state for a logical unit
302445039663SJohn Forte  * caller is responsible for establishing SCSI unit attention on
302545039663SJohn Forte  * state change
302645039663SJohn Forte  */
302745039663SJohn Forte stmf_status_t
stmf_set_lu_access(stmf_lu_t * lu,uint8_t access_state)302845039663SJohn Forte stmf_set_lu_access(stmf_lu_t *lu, uint8_t access_state)
302945039663SJohn Forte {
303045039663SJohn Forte 	stmf_i_lu_t *ilu;
303145039663SJohn Forte 	uint8_t *p1, *p2;
303245039663SJohn Forte 
303345039663SJohn Forte 	if ((access_state != STMF_LU_STANDBY) &&
303445039663SJohn Forte 	    (access_state != STMF_LU_ACTIVE)) {
303545039663SJohn Forte 		return (STMF_INVALID_ARG);
303645039663SJohn Forte 	}
303745039663SJohn Forte 
303845039663SJohn Forte 	p1 = &lu->lu_id->ident[0];
303945039663SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
304045039663SJohn Forte 	if (stmf_state.stmf_inventory_locked) {
304145039663SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
304245039663SJohn Forte 		return (STMF_BUSY);
304345039663SJohn Forte 	}
304445039663SJohn Forte 
304545039663SJohn Forte 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
304645039663SJohn Forte 		p2 = &ilu->ilu_lu->lu_id->ident[0];
304745039663SJohn Forte 		if (bcmp(p1, p2, 16) == 0) {
304845039663SJohn Forte 			break;
304945039663SJohn Forte 		}
305045039663SJohn Forte 	}
305145039663SJohn Forte 
305245039663SJohn Forte 	if (!ilu) {
305345039663SJohn Forte 		ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
305445039663SJohn Forte 	} else {
305545039663SJohn Forte 		/*
305645039663SJohn Forte 		 * We're changing access state on an existing logical unit
305745039663SJohn Forte 		 * Send the proxy registration message for this logical unit
305845039663SJohn Forte 		 * if we're in alua mode.
305945039663SJohn Forte 		 * If the requested state is STMF_LU_ACTIVE, we want to register
306045039663SJohn Forte 		 * this logical unit.
306145039663SJohn Forte 		 * If the requested state is STMF_LU_STANDBY, we're going to
306245039663SJohn Forte 		 * abort all tasks for this logical unit.
306345039663SJohn Forte 		 */
306445039663SJohn Forte 		if (stmf_state.stmf_alua_state == 1 &&
306545039663SJohn Forte 		    access_state == STMF_LU_ACTIVE) {
306645039663SJohn Forte 			stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
306745039663SJohn Forte 			stmf_ic_msg_t *ic_reg_lun;
306845039663SJohn Forte 			if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
306945039663SJohn Forte 			    lu->lu_lp->lp_alua_support) {
307045039663SJohn Forte 				ilu->ilu_alua = 1;
307145039663SJohn Forte 				/* allocate the register message */
307245039663SJohn Forte 				ic_reg_lun = ic_lun_active_msg_alloc(p1,
307345039663SJohn Forte 				    lu->lu_lp->lp_name,
307445039663SJohn Forte 				    lu->lu_proxy_reg_arg_len,
307545039663SJohn Forte 				    (uint8_t *)lu->lu_proxy_reg_arg,
307645039663SJohn Forte 				    stmf_proxy_msg_id);
307745039663SJohn Forte 				/* send the message */
307845039663SJohn Forte 				if (ic_reg_lun) {
307945039663SJohn Forte 					ic_ret = ic_tx_msg(ic_reg_lun);
308045039663SJohn Forte 					if (ic_ret == STMF_IC_MSG_SUCCESS) {
308145039663SJohn Forte 						stmf_proxy_msg_id++;
308245039663SJohn Forte 					}
308345039663SJohn Forte 				}
308445039663SJohn Forte 			}
308545039663SJohn Forte 		} else if (stmf_state.stmf_alua_state == 1 &&
308645039663SJohn Forte 		    access_state == STMF_LU_STANDBY) {
308745039663SJohn Forte 			/* abort all tasks for this lu */
308845039663SJohn Forte 			stmf_task_lu_killall(lu, NULL, STMF_ABORTED);
308945039663SJohn Forte 		}
309045039663SJohn Forte 	}
309145039663SJohn Forte 
309245039663SJohn Forte 	ilu->ilu_access = access_state;
309345039663SJohn Forte 
309445039663SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
309545039663SJohn Forte 	return (STMF_SUCCESS);
309645039663SJohn Forte }
309745039663SJohn Forte 
309845039663SJohn Forte 
3099fcf3ce44SJohn Forte stmf_status_t
stmf_register_lu(stmf_lu_t * lu)3100fcf3ce44SJohn Forte stmf_register_lu(stmf_lu_t *lu)
3101fcf3ce44SJohn Forte {
3102fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
3103fcf3ce44SJohn Forte 	uint8_t *p1, *p2;
3104fcf3ce44SJohn Forte 	stmf_state_change_info_t ssci;
3105fcf3ce44SJohn Forte 	stmf_id_data_t *luid;
3106fcf3ce44SJohn Forte 
3107fcf3ce44SJohn Forte 	if ((lu->lu_id->ident_type != ID_TYPE_NAA) ||
3108fcf3ce44SJohn Forte 	    (lu->lu_id->ident_length != 16) ||
3109fcf3ce44SJohn Forte 	    ((lu->lu_id->ident[0] & 0xf0) != 0x60)) {
3110fcf3ce44SJohn Forte 		return (STMF_INVALID_ARG);
3111fcf3ce44SJohn Forte 	}
3112fcf3ce44SJohn Forte 	p1 = &lu->lu_id->ident[0];
3113fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
3114fcf3ce44SJohn Forte 	if (stmf_state.stmf_inventory_locked) {
3115fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
3116fcf3ce44SJohn Forte 		return (STMF_BUSY);
3117fcf3ce44SJohn Forte 	}
3118fcf3ce44SJohn Forte 
3119fcf3ce44SJohn Forte 	for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
3120fcf3ce44SJohn Forte 		p2 = &ilu->ilu_lu->lu_id->ident[0];
3121fcf3ce44SJohn Forte 		if (bcmp(p1, p2, 16) == 0) {
3122fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
3123fcf3ce44SJohn Forte 			return (STMF_ALREADY);
3124fcf3ce44SJohn Forte 		}
3125fcf3ce44SJohn Forte 	}
3126fcf3ce44SJohn Forte 
3127fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3128fcf3ce44SJohn Forte 	luid = stmf_lookup_id(&stmf_state.stmf_luid_list,
3129fcf3ce44SJohn Forte 	    lu->lu_id->ident_length, lu->lu_id->ident);
3130fcf3ce44SJohn Forte 	if (luid) {
3131fcf3ce44SJohn Forte 		luid->id_pt_to_object = (void *)ilu;
3132fcf3ce44SJohn Forte 		ilu->ilu_luid = luid;
3133fcf3ce44SJohn Forte 	}
3134fcf3ce44SJohn Forte 	ilu->ilu_alias = NULL;
3135fcf3ce44SJohn Forte 
3136fcf3ce44SJohn Forte 	ilu->ilu_next = stmf_state.stmf_ilulist;
3137fcf3ce44SJohn Forte 	ilu->ilu_prev = NULL;
3138fcf3ce44SJohn Forte 	if (ilu->ilu_next)
3139fcf3ce44SJohn Forte 		ilu->ilu_next->ilu_prev = ilu;
3140fcf3ce44SJohn Forte 	stmf_state.stmf_ilulist = ilu;
3141fcf3ce44SJohn Forte 	stmf_state.stmf_nlus++;
3142fcf3ce44SJohn Forte 	if (lu->lu_lp) {
3143fcf3ce44SJohn Forte 		((stmf_i_lu_provider_t *)
3144fcf3ce44SJohn Forte 		    (lu->lu_lp->lp_stmf_private))->ilp_nlus++;
3145fcf3ce44SJohn Forte 	}
3146fcf3ce44SJohn Forte 	ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
3147fcf3ce44SJohn Forte 	STMF_EVENT_ALLOC_HANDLE(ilu->ilu_event_hdl);
3148a49dc893SSaso Kiselkov 	cv_init(&ilu->ilu_offline_pending_cv, NULL, CV_DRIVER, NULL);
3149034d83c4Stim szeto 	stmf_create_kstat_lu(ilu);
315045039663SJohn Forte 	/*
315145039663SJohn Forte 	 * register with proxy module if available and logical unit
315245039663SJohn Forte 	 * is in active state
315345039663SJohn Forte 	 */
315445039663SJohn Forte 	if (stmf_state.stmf_alua_state == 1 &&
315545039663SJohn Forte 	    ilu->ilu_access == STMF_LU_ACTIVE) {
315645039663SJohn Forte 		stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
315745039663SJohn Forte 		stmf_ic_msg_t *ic_reg_lun;
315845039663SJohn Forte 		if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
315945039663SJohn Forte 		    lu->lu_lp->lp_alua_support) {
316045039663SJohn Forte 			ilu->ilu_alua = 1;
316145039663SJohn Forte 			/* allocate the register message */
316245039663SJohn Forte 			ic_reg_lun = ic_reg_lun_msg_alloc(p1,
316345039663SJohn Forte 			    lu->lu_lp->lp_name, lu->lu_proxy_reg_arg_len,
316445039663SJohn Forte 			    (uint8_t *)lu->lu_proxy_reg_arg, stmf_proxy_msg_id);
316545039663SJohn Forte 			/* send the message */
316645039663SJohn Forte 			if (ic_reg_lun) {
316745039663SJohn Forte 				ic_ret = ic_tx_msg(ic_reg_lun);
316845039663SJohn Forte 				if (ic_ret == STMF_IC_MSG_SUCCESS) {
316945039663SJohn Forte 					stmf_proxy_msg_id++;
317045039663SJohn Forte 				}
317145039663SJohn Forte 			}
317245039663SJohn Forte 		}
317345039663SJohn Forte 	}
3174fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
3175fcf3ce44SJohn Forte 
31764b31676fSsrivijitha dugganapalli 	/*  check the default state for lu */
31774b31676fSsrivijitha dugganapalli 	if (stmf_state.stmf_default_lu_state == STMF_STATE_OFFLINE) {
31784b31676fSsrivijitha dugganapalli 		ilu->ilu_prev_state = STMF_STATE_OFFLINE;
31794b31676fSsrivijitha dugganapalli 	} else {
3180fcf3ce44SJohn Forte 		ilu->ilu_prev_state = STMF_STATE_ONLINE;
3181fcf3ce44SJohn Forte 		if (stmf_state.stmf_service_running) {
3182fcf3ce44SJohn Forte 			ssci.st_rflags = 0;
3183fcf3ce44SJohn Forte 			ssci.st_additional_info = NULL;
3184fcf3ce44SJohn Forte 			(void) stmf_ctl(STMF_CMD_LU_ONLINE, lu, &ssci);
3185fcf3ce44SJohn Forte 		}
31864b31676fSsrivijitha dugganapalli 	}
3187fcf3ce44SJohn Forte 
3188fcf3ce44SJohn Forte 	/* XXX: Generate event */
3189fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
3190fcf3ce44SJohn Forte }
3191fcf3ce44SJohn Forte 
3192fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_lu(stmf_lu_t * lu)3193fcf3ce44SJohn Forte stmf_deregister_lu(stmf_lu_t *lu)
3194fcf3ce44SJohn Forte {
3195fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
3196fcf3ce44SJohn Forte 
3197fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
3198fcf3ce44SJohn Forte 	if (stmf_state.stmf_inventory_locked) {
3199fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
3200fcf3ce44SJohn Forte 		return (STMF_BUSY);
3201fcf3ce44SJohn Forte 	}
3202fcf3ce44SJohn Forte 	ilu = stmf_lookup_lu(lu);
3203fcf3ce44SJohn Forte 	if (ilu == NULL) {
3204fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
3205fcf3ce44SJohn Forte 		return (STMF_INVALID_ARG);
3206fcf3ce44SJohn Forte 	}
3207fcf3ce44SJohn Forte 	if (ilu->ilu_state == STMF_STATE_OFFLINE) {
3208fcf3ce44SJohn Forte 		ASSERT(ilu->ilu_ntasks == ilu->ilu_ntasks_free);
3209fcf3ce44SJohn Forte 		while (ilu->ilu_flags & ILU_STALL_DEREGISTER) {
3210fcf3ce44SJohn Forte 			cv_wait(&stmf_state.stmf_cv, &stmf_state.stmf_lock);
3211fcf3ce44SJohn Forte 		}
3212fcf3ce44SJohn Forte 		if (ilu->ilu_ntasks) {
3213fcf3ce44SJohn Forte 			stmf_i_scsi_task_t *itask, *nitask;
3214fcf3ce44SJohn Forte 
3215fcf3ce44SJohn Forte 			nitask = ilu->ilu_tasks;
3216fcf3ce44SJohn Forte 			do {
3217fcf3ce44SJohn Forte 				itask = nitask;
3218fcf3ce44SJohn Forte 				nitask = itask->itask_lu_next;
3219fcf3ce44SJohn Forte 				lu->lu_task_free(itask->itask_task);
3220fcf3ce44SJohn Forte 				stmf_free(itask->itask_task);
3221fcf3ce44SJohn Forte 			} while (nitask != NULL);
3222fcf3ce44SJohn Forte 
3223fcf3ce44SJohn Forte 			ilu->ilu_tasks = ilu->ilu_free_tasks = NULL;
3224fcf3ce44SJohn Forte 			ilu->ilu_ntasks = ilu->ilu_ntasks_free = 0;
3225fcf3ce44SJohn Forte 		}
322645039663SJohn Forte 		/* de-register with proxy if available */
322745039663SJohn Forte 		if (ilu->ilu_access == STMF_LU_ACTIVE &&
322845039663SJohn Forte 		    stmf_state.stmf_alua_state == 1) {
322945039663SJohn Forte 			/* de-register with proxy module */
323045039663SJohn Forte 			stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
323145039663SJohn Forte 			stmf_ic_msg_t *ic_dereg_lun;
323245039663SJohn Forte 			if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
323345039663SJohn Forte 			    lu->lu_lp->lp_alua_support) {
323445039663SJohn Forte 				ilu->ilu_alua = 1;
323545039663SJohn Forte 				/* allocate the de-register message */
323645039663SJohn Forte 				ic_dereg_lun = ic_dereg_lun_msg_alloc(
323745039663SJohn Forte 				    lu->lu_id->ident, lu->lu_lp->lp_name, 0,
323845039663SJohn Forte 				    NULL, stmf_proxy_msg_id);
323945039663SJohn Forte 				/* send the message */
324045039663SJohn Forte 				if (ic_dereg_lun) {
324145039663SJohn Forte 					ic_ret = ic_tx_msg(ic_dereg_lun);
324245039663SJohn Forte 					if (ic_ret == STMF_IC_MSG_SUCCESS) {
324345039663SJohn Forte 						stmf_proxy_msg_id++;
324445039663SJohn Forte 					}
324545039663SJohn Forte 				}
324645039663SJohn Forte 			}
324745039663SJohn Forte 		}
3248fcf3ce44SJohn Forte 
3249fcf3ce44SJohn Forte 		if (ilu->ilu_next)
3250fcf3ce44SJohn Forte 			ilu->ilu_next->ilu_prev = ilu->ilu_prev;
3251fcf3ce44SJohn Forte 		if (ilu->ilu_prev)
3252fcf3ce44SJohn Forte 			ilu->ilu_prev->ilu_next = ilu->ilu_next;
3253fcf3ce44SJohn Forte 		else
3254fcf3ce44SJohn Forte 			stmf_state.stmf_ilulist = ilu->ilu_next;
3255fcf3ce44SJohn Forte 		stmf_state.stmf_nlus--;
3256fcf3ce44SJohn Forte 
3257fcf3ce44SJohn Forte 		if (ilu == stmf_state.stmf_svc_ilu_draining) {
3258fcf3ce44SJohn Forte 			stmf_state.stmf_svc_ilu_draining = ilu->ilu_next;
3259fcf3ce44SJohn Forte 		}
3260fcf3ce44SJohn Forte 		if (ilu == stmf_state.stmf_svc_ilu_timing) {
3261fcf3ce44SJohn Forte 			stmf_state.stmf_svc_ilu_timing = ilu->ilu_next;
3262fcf3ce44SJohn Forte 		}
3263fcf3ce44SJohn Forte 		if (lu->lu_lp) {
3264fcf3ce44SJohn Forte 			((stmf_i_lu_provider_t *)
3265fcf3ce44SJohn Forte 			    (lu->lu_lp->lp_stmf_private))->ilp_nlus--;
3266fcf3ce44SJohn Forte 		}
3267fcf3ce44SJohn Forte 		if (ilu->ilu_luid) {
3268fcf3ce44SJohn Forte 			((stmf_id_data_t *)ilu->ilu_luid)->id_pt_to_object =
3269fcf3ce44SJohn Forte 			    NULL;
3270fcf3ce44SJohn Forte 			ilu->ilu_luid = NULL;
3271fcf3ce44SJohn Forte 		}
3272fcf3ce44SJohn Forte 		STMF_EVENT_FREE_HANDLE(ilu->ilu_event_hdl);
3273fcf3ce44SJohn Forte 	} else {
3274fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
3275fcf3ce44SJohn Forte 		return (STMF_BUSY);
3276fcf3ce44SJohn Forte 	}
3277034d83c4Stim szeto 	if (ilu->ilu_kstat_info) {
32783c9850a6SDan McDonald 		kmem_free(ilu->ilu_kstat_info->ks_data, STMF_KSTAT_LU_SZ);
3279034d83c4Stim szeto 		kstat_delete(ilu->ilu_kstat_info);
3280034d83c4Stim szeto 	}
3281034d83c4Stim szeto 	if (ilu->ilu_kstat_io) {
3282034d83c4Stim szeto 		kstat_delete(ilu->ilu_kstat_io);
3283034d83c4Stim szeto 		mutex_destroy(&ilu->ilu_kstat_lock);
3284034d83c4Stim szeto 	}
3285a49dc893SSaso Kiselkov 	cv_destroy(&ilu->ilu_offline_pending_cv);
3286fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
3287fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
3288fcf3ce44SJohn Forte }
3289fcf3ce44SJohn Forte 
329045039663SJohn Forte void
stmf_set_port_standby(stmf_local_port_t * lport,uint16_t rtpid)329145039663SJohn Forte stmf_set_port_standby(stmf_local_port_t *lport, uint16_t rtpid)
329245039663SJohn Forte {
329345039663SJohn Forte 	stmf_i_local_port_t *ilport =
329445039663SJohn Forte 	    (stmf_i_local_port_t *)lport->lport_stmf_private;
329545039663SJohn Forte 	ilport->ilport_rtpid = rtpid;
329645039663SJohn Forte 	ilport->ilport_standby = 1;
329745039663SJohn Forte }
329845039663SJohn Forte 
3299cd36db67SJohn Forte void
stmf_set_port_alua(stmf_local_port_t * lport)3300cd36db67SJohn Forte stmf_set_port_alua(stmf_local_port_t *lport)
3301cd36db67SJohn Forte {
3302cd36db67SJohn Forte 	stmf_i_local_port_t *ilport =
3303cd36db67SJohn Forte 	    (stmf_i_local_port_t *)lport->lport_stmf_private;
3304cd36db67SJohn Forte 	ilport->ilport_alua = 1;
3305cd36db67SJohn Forte }
3306cd36db67SJohn Forte 
3307fcf3ce44SJohn Forte stmf_status_t
stmf_register_local_port(stmf_local_port_t * lport)3308fcf3ce44SJohn Forte stmf_register_local_port(stmf_local_port_t *lport)
3309fcf3ce44SJohn Forte {
3310fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
3311fcf3ce44SJohn Forte 	stmf_state_change_info_t ssci;
3312fcf3ce44SJohn Forte 	int start_workers = 0;
3313fcf3ce44SJohn Forte 
3314fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
3315fcf3ce44SJohn Forte 	if (stmf_state.stmf_inventory_locked) {
3316fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
3317fcf3ce44SJohn Forte 		return (STMF_BUSY);
3318fcf3ce44SJohn Forte 	}
3319fcf3ce44SJohn Forte 	ilport = (stmf_i_local_port_t *)lport->lport_stmf_private;
3320fcf3ce44SJohn Forte 	rw_init(&ilport->ilport_lock, NULL, RW_DRIVER, NULL);
3321fcf3ce44SJohn Forte 
3322427fcaf8Stim szeto 	ilport->ilport_instance =
3323427fcaf8Stim szeto 	    id_alloc_nosleep(stmf_state.stmf_ilport_inst_space);
3324427fcaf8Stim szeto 	if (ilport->ilport_instance == -1) {
3325427fcaf8Stim szeto 		mutex_exit(&stmf_state.stmf_lock);
3326427fcaf8Stim szeto 		return (STMF_FAILURE);
3327427fcaf8Stim szeto 	}
3328fcf3ce44SJohn Forte 	ilport->ilport_next = stmf_state.stmf_ilportlist;
3329fcf3ce44SJohn Forte 	ilport->ilport_prev = NULL;
3330fcf3ce44SJohn Forte 	if (ilport->ilport_next)
3331fcf3ce44SJohn Forte 		ilport->ilport_next->ilport_prev = ilport;
3332fcf3ce44SJohn Forte 	stmf_state.stmf_ilportlist = ilport;
3333fcf3ce44SJohn Forte 	stmf_state.stmf_nlports++;
3334fcf3ce44SJohn Forte 	if (lport->lport_pp) {
3335fcf3ce44SJohn Forte 		((stmf_i_port_provider_t *)
3336fcf3ce44SJohn Forte 		    (lport->lport_pp->pp_stmf_private))->ipp_npps++;
3337fcf3ce44SJohn Forte 	}
3338fcf3ce44SJohn Forte 	ilport->ilport_tg =
3339fcf3ce44SJohn Forte 	    stmf_lookup_group_for_target(lport->lport_id->ident,
3340fcf3ce44SJohn Forte 	    lport->lport_id->ident_length);
334145039663SJohn Forte 
334245039663SJohn Forte 	/*
334345039663SJohn Forte 	 * rtpid will/must be set if this is a standby port
334445039663SJohn Forte 	 * only register ports that are not standby (proxy) ports
3345cd36db67SJohn Forte 	 * and ports that are alua participants (ilport_alua == 1)
334645039663SJohn Forte 	 */
334745039663SJohn Forte 	if (ilport->ilport_standby == 0) {
33481a5e258fSJosef 'Jeff' Sipek 		ilport->ilport_rtpid = atomic_inc_16_nv(&stmf_rtpid_counter);
334945039663SJohn Forte 	}
335045039663SJohn Forte 
335145039663SJohn Forte 	if (stmf_state.stmf_alua_state == 1 &&
3352cd36db67SJohn Forte 	    ilport->ilport_standby == 0 &&
3353cd36db67SJohn Forte 	    ilport->ilport_alua == 1) {
335445039663SJohn Forte 		stmf_ic_msg_t *ic_reg_port;
335545039663SJohn Forte 		stmf_ic_msg_status_t ic_ret;
335645039663SJohn Forte 		stmf_local_port_t *lport;
335745039663SJohn Forte 		lport = ilport->ilport_lport;
335845039663SJohn Forte 		ic_reg_port = ic_reg_port_msg_alloc(
335945039663SJohn Forte 		    lport->lport_id, ilport->ilport_rtpid,
336045039663SJohn Forte 		    0, NULL, stmf_proxy_msg_id);
336145039663SJohn Forte 		if (ic_reg_port) {
336245039663SJohn Forte 			ic_ret = ic_tx_msg(ic_reg_port);
336345039663SJohn Forte 			if (ic_ret == STMF_IC_MSG_SUCCESS) {
336445039663SJohn Forte 				ilport->ilport_reg_msgid = stmf_proxy_msg_id++;
336545039663SJohn Forte 			} else {
336645039663SJohn Forte 				cmn_err(CE_WARN, "error on port registration "
336745039663SJohn Forte 				"port - %s", ilport->ilport_kstat_tgt_name);
336845039663SJohn Forte 			}
336945039663SJohn Forte 		}
337045039663SJohn Forte 	}
3371fcf3ce44SJohn Forte 	STMF_EVENT_ALLOC_HANDLE(ilport->ilport_event_hdl);
3372034d83c4Stim szeto 	stmf_create_kstat_lport(ilport);
3373fcf3ce44SJohn Forte 	if (stmf_workers_state == STMF_WORKERS_DISABLED) {
3374fcf3ce44SJohn Forte 		stmf_workers_state = STMF_WORKERS_ENABLING;
3375fcf3ce44SJohn Forte 		start_workers = 1;
3376fcf3ce44SJohn Forte 	}
3377fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
3378fcf3ce44SJohn Forte 
3379fcf3ce44SJohn Forte 	if (start_workers)
3380fcf3ce44SJohn Forte 		stmf_worker_init();
3381fcf3ce44SJohn Forte 
33824b31676fSsrivijitha dugganapalli 	/*  the default state of LPORT */
33834b31676fSsrivijitha dugganapalli 
33844b31676fSsrivijitha dugganapalli 	if (stmf_state.stmf_default_lport_state == STMF_STATE_OFFLINE) {
33854b31676fSsrivijitha dugganapalli 		ilport->ilport_prev_state = STMF_STATE_OFFLINE;
33864b31676fSsrivijitha dugganapalli 	} else {
3387fcf3ce44SJohn Forte 		ilport->ilport_prev_state = STMF_STATE_ONLINE;
3388fcf3ce44SJohn Forte 		if (stmf_state.stmf_service_running) {
3389fcf3ce44SJohn Forte 			ssci.st_rflags = 0;
3390fcf3ce44SJohn Forte 			ssci.st_additional_info = NULL;
3391fcf3ce44SJohn Forte 			(void) stmf_ctl(STMF_CMD_LPORT_ONLINE, lport, &ssci);
3392fcf3ce44SJohn Forte 		}
33934b31676fSsrivijitha dugganapalli 	}
3394fcf3ce44SJohn Forte 
3395fcf3ce44SJohn Forte 	/* XXX: Generate event */
3396fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
3397fcf3ce44SJohn Forte }
3398fcf3ce44SJohn Forte 
3399fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_local_port(stmf_local_port_t * lport)3400fcf3ce44SJohn Forte stmf_deregister_local_port(stmf_local_port_t *lport)
3401fcf3ce44SJohn Forte {
3402fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
3403fcf3ce44SJohn Forte 
3404fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
3405fcf3ce44SJohn Forte 	if (stmf_state.stmf_inventory_locked) {
3406fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
3407fcf3ce44SJohn Forte 		return (STMF_BUSY);
3408fcf3ce44SJohn Forte 	}
340945039663SJohn Forte 
34106ac72a9cSAlexander Stetsenko 	/* dequeue all object requests from active queue */
34116ac72a9cSAlexander Stetsenko 	stmf_svc_kill_obj_requests(lport);
34126ac72a9cSAlexander Stetsenko 
3413fcf3ce44SJohn Forte 	ilport = (stmf_i_local_port_t *)lport->lport_stmf_private;
341445039663SJohn Forte 
341545039663SJohn Forte 	/*
341645039663SJohn Forte 	 * deregister ports that are not standby (proxy)
341745039663SJohn Forte 	 */
341845039663SJohn Forte 	if (stmf_state.stmf_alua_state == 1 &&
3419cd36db67SJohn Forte 	    ilport->ilport_standby == 0 &&
3420cd36db67SJohn Forte 	    ilport->ilport_alua == 1) {
342145039663SJohn Forte 		stmf_ic_msg_t *ic_dereg_port;
342245039663SJohn Forte 		stmf_ic_msg_status_t ic_ret;
342345039663SJohn Forte 		ic_dereg_port = ic_dereg_port_msg_alloc(
342445039663SJohn Forte 		    lport->lport_id, 0, NULL, stmf_proxy_msg_id);
342545039663SJohn Forte 		if (ic_dereg_port) {
342645039663SJohn Forte 			ic_ret = ic_tx_msg(ic_dereg_port);
342745039663SJohn Forte 			if (ic_ret == STMF_IC_MSG_SUCCESS) {
342845039663SJohn Forte 				stmf_proxy_msg_id++;
342945039663SJohn Forte 			}
343045039663SJohn Forte 		}
343145039663SJohn Forte 	}
343245039663SJohn Forte 
3433fcf3ce44SJohn Forte 	if (ilport->ilport_nsessions == 0) {
3434fcf3ce44SJohn Forte 		if (ilport->ilport_next)
3435fcf3ce44SJohn Forte 			ilport->ilport_next->ilport_prev = ilport->ilport_prev;
3436fcf3ce44SJohn Forte 		if (ilport->ilport_prev)
3437fcf3ce44SJohn Forte 			ilport->ilport_prev->ilport_next = ilport->ilport_next;
3438fcf3ce44SJohn Forte 		else
3439fcf3ce44SJohn Forte 			stmf_state.stmf_ilportlist = ilport->ilport_next;
3440427fcaf8Stim szeto 		id_free(stmf_state.stmf_ilport_inst_space,
3441427fcaf8Stim szeto 		    ilport->ilport_instance);
3442fcf3ce44SJohn Forte 		rw_destroy(&ilport->ilport_lock);
3443fcf3ce44SJohn Forte 		stmf_state.stmf_nlports--;
3444fcf3ce44SJohn Forte 		if (lport->lport_pp) {
3445fcf3ce44SJohn Forte 			((stmf_i_port_provider_t *)
3446fcf3ce44SJohn Forte 			    (lport->lport_pp->pp_stmf_private))->ipp_npps--;
3447fcf3ce44SJohn Forte 		}
3448fcf3ce44SJohn Forte 		ilport->ilport_tg = NULL;
3449fcf3ce44SJohn Forte 		STMF_EVENT_FREE_HANDLE(ilport->ilport_event_hdl);
3450fcf3ce44SJohn Forte 	} else {
3451fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
3452fcf3ce44SJohn Forte 		return (STMF_BUSY);
3453fcf3ce44SJohn Forte 	}
3454034d83c4Stim szeto 	if (ilport->ilport_kstat_info) {
3455554c2b16Stim szeto 		kmem_free(ilport->ilport_kstat_info->ks_data,
34563c9850a6SDan McDonald 		    STMF_KSTAT_TGT_SZ);
3457034d83c4Stim szeto 		kstat_delete(ilport->ilport_kstat_info);
3458034d83c4Stim szeto 	}
3459034d83c4Stim szeto 	if (ilport->ilport_kstat_io) {
3460034d83c4Stim szeto 		kstat_delete(ilport->ilport_kstat_io);
3461034d83c4Stim szeto 		mutex_destroy(&ilport->ilport_kstat_lock);
3462034d83c4Stim szeto 	}
3463fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
3464fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
3465fcf3ce44SJohn Forte }
3466fcf3ce44SJohn Forte 
3467fcf3ce44SJohn Forte /*
3468427fcaf8Stim szeto  * Rport id/instance mappings remain valid until STMF is unloaded
3469427fcaf8Stim szeto  */
3470427fcaf8Stim szeto static int
stmf_irport_compare(const void * void_irport1,const void * void_irport2)3471427fcaf8Stim szeto stmf_irport_compare(const void *void_irport1, const void *void_irport2)
3472427fcaf8Stim szeto {
3473427fcaf8Stim szeto 	const	stmf_i_remote_port_t	*irport1 = void_irport1;
3474427fcaf8Stim szeto 	const	stmf_i_remote_port_t	*irport2 = void_irport2;
3475427fcaf8Stim szeto 	int			result;
3476427fcaf8Stim szeto 
3477427fcaf8Stim szeto 	/* Sort by code set then ident */
3478427fcaf8Stim szeto 	if (irport1->irport_id->code_set <
3479427fcaf8Stim szeto 	    irport2->irport_id->code_set) {
3480427fcaf8Stim szeto 		return (-1);
3481427fcaf8Stim szeto 	} else if (irport1->irport_id->code_set >
3482427fcaf8Stim szeto 	    irport2->irport_id->code_set) {
3483427fcaf8Stim szeto 		return (1);
3484427fcaf8Stim szeto 	}
3485427fcaf8Stim szeto 
3486427fcaf8Stim szeto 	/* Next by ident length */
3487427fcaf8Stim szeto 	if (irport1->irport_id->ident_length <
3488427fcaf8Stim szeto 	    irport2->irport_id->ident_length) {
3489427fcaf8Stim szeto 		return (-1);
3490427fcaf8Stim szeto 	} else if (irport1->irport_id->ident_length >
3491427fcaf8Stim szeto 	    irport2->irport_id->ident_length) {
3492427fcaf8Stim szeto 		return (1);
3493427fcaf8Stim szeto 	}
3494427fcaf8Stim szeto 
3495427fcaf8Stim szeto 	/* Code set and ident length both match, now compare idents */
3496427fcaf8Stim szeto 	result = memcmp(irport1->irport_id->ident,
3497427fcaf8Stim szeto 	    irport2->irport_id->ident,
3498427fcaf8Stim szeto 	    irport1->irport_id->ident_length);
3499427fcaf8Stim szeto 
3500427fcaf8Stim szeto 	if (result < 0) {
3501427fcaf8Stim szeto 		return (-1);
3502427fcaf8Stim szeto 	} else if (result > 0) {
3503427fcaf8Stim szeto 		return (1);
3504427fcaf8Stim szeto 	}
3505427fcaf8Stim szeto 
3506427fcaf8Stim szeto 	return (0);
3507427fcaf8Stim szeto }
3508427fcaf8Stim szeto 
3509427fcaf8Stim szeto static stmf_i_remote_port_t *
stmf_irport_create(scsi_devid_desc_t * rport_devid)3510427fcaf8Stim szeto stmf_irport_create(scsi_devid_desc_t *rport_devid)
3511427fcaf8Stim szeto {
3512427fcaf8Stim szeto 	int			alloc_len;
3513427fcaf8Stim szeto 	stmf_i_remote_port_t	*irport;
3514427fcaf8Stim szeto 
3515427fcaf8Stim szeto 	/*
3516427fcaf8Stim szeto 	 * Lookup will bump the refcnt if there's an existing rport
3517427fcaf8Stim szeto 	 * context for this identifier.
3518427fcaf8Stim szeto 	 */
3519427fcaf8Stim szeto 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3520427fcaf8Stim szeto 
3521427fcaf8Stim szeto 	alloc_len = sizeof (*irport) + sizeof (scsi_devid_desc_t) +
3522427fcaf8Stim szeto 	    rport_devid->ident_length - 1;
3523427fcaf8Stim szeto 	irport = kmem_zalloc(alloc_len, KM_NOSLEEP);
3524427fcaf8Stim szeto 	if (irport == NULL) {
3525427fcaf8Stim szeto 		return (NULL);
3526427fcaf8Stim szeto 	}
3527427fcaf8Stim szeto 
3528427fcaf8Stim szeto 	irport->irport_instance =
3529427fcaf8Stim szeto 	    id_alloc_nosleep(stmf_state.stmf_irport_inst_space);
3530427fcaf8Stim szeto 	if (irport->irport_instance == -1) {
3531427fcaf8Stim szeto 		kmem_free(irport, alloc_len);
3532427fcaf8Stim szeto 		return (NULL);
3533427fcaf8Stim szeto 	}
3534427fcaf8Stim szeto 
3535427fcaf8Stim szeto 	irport->irport_id =
3536427fcaf8Stim szeto 	    (struct scsi_devid_desc *)(irport + 1); /* Ptr. Arith. */
3537427fcaf8Stim szeto 	bcopy(rport_devid, irport->irport_id,
3538427fcaf8Stim szeto 	    sizeof (scsi_devid_desc_t) + rport_devid->ident_length - 1);
3539427fcaf8Stim szeto 	irport->irport_refcnt = 1;
3540427fcaf8Stim szeto 	mutex_init(&irport->irport_mutex, NULL, MUTEX_DEFAULT, NULL);
354161dfa509SRick McNeal 	irport->irport_rdstart_timestamp = LLONG_MAX;
354261dfa509SRick McNeal 	irport->irport_wrstart_timestamp = LLONG_MAX;
3543427fcaf8Stim szeto 
3544427fcaf8Stim szeto 	return (irport);
3545427fcaf8Stim szeto }
3546427fcaf8Stim szeto 
3547427fcaf8Stim szeto static void
stmf_irport_destroy(stmf_i_remote_port_t * irport)3548427fcaf8Stim szeto stmf_irport_destroy(stmf_i_remote_port_t *irport)
3549427fcaf8Stim szeto {
355061dfa509SRick McNeal 	stmf_destroy_kstat_rport(irport);
3551427fcaf8Stim szeto 	id_free(stmf_state.stmf_irport_inst_space, irport->irport_instance);
3552427fcaf8Stim szeto 	mutex_destroy(&irport->irport_mutex);
3553427fcaf8Stim szeto 	kmem_free(irport, sizeof (*irport) + sizeof (scsi_devid_desc_t) +
3554427fcaf8Stim szeto 	    irport->irport_id->ident_length - 1);
3555427fcaf8Stim szeto }
3556427fcaf8Stim szeto 
355761dfa509SRick McNeal static void
stmf_create_kstat_rport(stmf_i_remote_port_t * irport)355861dfa509SRick McNeal stmf_create_kstat_rport(stmf_i_remote_port_t *irport)
355961dfa509SRick McNeal {
356061dfa509SRick McNeal 	scsi_devid_desc_t *id = irport->irport_id;
356161dfa509SRick McNeal 	char ks_nm[KSTAT_STRLEN];
356261dfa509SRick McNeal 	stmf_kstat_rport_info_t *ks_info;
356361dfa509SRick McNeal 	stmf_kstat_rport_estat_t *ks_estat;
356461dfa509SRick McNeal 	char *ident = NULL;
356561dfa509SRick McNeal 
356661dfa509SRick McNeal 	ks_info = kmem_zalloc(sizeof (*ks_info), KM_NOSLEEP);
356761dfa509SRick McNeal 	if (ks_info == NULL)
356861dfa509SRick McNeal 		goto err_out;
356961dfa509SRick McNeal 
357061dfa509SRick McNeal 	(void) snprintf(ks_nm, KSTAT_STRLEN, "stmf_rport_%"PRIxPTR"",
357161dfa509SRick McNeal 	    (uintptr_t)irport);
357261dfa509SRick McNeal 	irport->irport_kstat_info = kstat_create(STMF_MODULE_NAME, 0,
357361dfa509SRick McNeal 	    ks_nm, "misc", KSTAT_TYPE_NAMED,
357461dfa509SRick McNeal 	    STMF_KSTAT_RPORT_DATAMAX - STMF_RPORT_INFO_LIMIT,
357561dfa509SRick McNeal 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_VAR_SIZE);
357661dfa509SRick McNeal 	if (irport->irport_kstat_info == NULL) {
357761dfa509SRick McNeal 		kmem_free(ks_info, sizeof (*ks_info));
357861dfa509SRick McNeal 		goto err_out;
357961dfa509SRick McNeal 	}
358061dfa509SRick McNeal 
358161dfa509SRick McNeal 	irport->irport_kstat_info->ks_data = ks_info;
358261dfa509SRick McNeal 	irport->irport_kstat_info->ks_private = irport;
358361dfa509SRick McNeal 	irport->irport_kstat_info->ks_update = stmf_kstat_rport_update;
358461dfa509SRick McNeal 	ident = kmem_alloc(id->ident_length + 1, KM_NOSLEEP);
358561dfa509SRick McNeal 	if (ident == NULL) {
358661dfa509SRick McNeal 		kstat_delete(irport->irport_kstat_info);
358761dfa509SRick McNeal 		irport->irport_kstat_info = NULL;
358861dfa509SRick McNeal 		kmem_free(ks_info, sizeof (*ks_info));
358961dfa509SRick McNeal 		goto err_out;
359061dfa509SRick McNeal 	}
359161dfa509SRick McNeal 
359261dfa509SRick McNeal 	(void) memcpy(ident, id->ident, id->ident_length);
359361dfa509SRick McNeal 	ident[id->ident_length] = '\0';
359461dfa509SRick McNeal 	kstat_named_init(&ks_info->i_rport_name, "name", KSTAT_DATA_STRING);
359561dfa509SRick McNeal 	kstat_named_init(&ks_info->i_protocol, "protocol",
359661dfa509SRick McNeal 	    KSTAT_DATA_STRING);
359761dfa509SRick McNeal 
359861dfa509SRick McNeal 	kstat_named_setstr(&ks_info->i_rport_name, ident);
359961dfa509SRick McNeal 	kstat_named_setstr(&ks_info->i_protocol,
360061dfa509SRick McNeal 	    protocol_ident[irport->irport_id->protocol_id]);
360161dfa509SRick McNeal 	irport->irport_kstat_info->ks_lock = &irport->irport_mutex;
360261dfa509SRick McNeal 	irport->irport_info_dirty = B_TRUE;
360361dfa509SRick McNeal 	kstat_install(irport->irport_kstat_info);
360461dfa509SRick McNeal 
360561dfa509SRick McNeal 	(void) snprintf(ks_nm, KSTAT_STRLEN, "stmf_rport_io_%"PRIxPTR"",
360661dfa509SRick McNeal 	    (uintptr_t)irport);
360761dfa509SRick McNeal 	irport->irport_kstat_io = kstat_create(STMF_MODULE_NAME, 0, ks_nm,
360861dfa509SRick McNeal 	    "io", KSTAT_TYPE_IO, 1, 0);
360961dfa509SRick McNeal 	if (irport->irport_kstat_io == NULL)
361061dfa509SRick McNeal 		goto err_out;
361161dfa509SRick McNeal 
361261dfa509SRick McNeal 	irport->irport_kstat_io->ks_lock = &irport->irport_mutex;
361361dfa509SRick McNeal 	kstat_install(irport->irport_kstat_io);
361461dfa509SRick McNeal 
361561dfa509SRick McNeal 	(void) snprintf(ks_nm, KSTAT_STRLEN, "stmf_rport_st_%"PRIxPTR"",
361661dfa509SRick McNeal 	    (uintptr_t)irport);
361761dfa509SRick McNeal 	irport->irport_kstat_estat = kstat_create(STMF_MODULE_NAME, 0, ks_nm,
361861dfa509SRick McNeal 	    "misc", KSTAT_TYPE_NAMED,
361961dfa509SRick McNeal 	    sizeof (*ks_estat) / sizeof (kstat_named_t), 0);
362061dfa509SRick McNeal 	if (irport->irport_kstat_estat == NULL)
362161dfa509SRick McNeal 		goto err_out;
362261dfa509SRick McNeal 
362361dfa509SRick McNeal 	ks_estat = (stmf_kstat_rport_estat_t *)KSTAT_NAMED_PTR(
362461dfa509SRick McNeal 	    irport->irport_kstat_estat);
362561dfa509SRick McNeal 	kstat_named_init(&ks_estat->i_rport_read_latency,
362661dfa509SRick McNeal 	    "rlatency", KSTAT_DATA_UINT64);
362761dfa509SRick McNeal 	kstat_named_init(&ks_estat->i_rport_write_latency,
362861dfa509SRick McNeal 	    "wlatency", KSTAT_DATA_UINT64);
362961dfa509SRick McNeal 	kstat_named_init(&ks_estat->i_nread_tasks, "rntasks",
363061dfa509SRick McNeal 	    KSTAT_DATA_UINT64);
363161dfa509SRick McNeal 	kstat_named_init(&ks_estat->i_nwrite_tasks, "wntasks",
363261dfa509SRick McNeal 	    KSTAT_DATA_UINT64);
363361dfa509SRick McNeal 	irport->irport_kstat_estat->ks_lock = &irport->irport_mutex;
363461dfa509SRick McNeal 	kstat_install(irport->irport_kstat_estat);
363561dfa509SRick McNeal 
363661dfa509SRick McNeal 	return;
363761dfa509SRick McNeal 
363861dfa509SRick McNeal err_out:
363961dfa509SRick McNeal 	(void) memcpy(ks_nm, id->ident, MAX(KSTAT_STRLEN - 1,
364061dfa509SRick McNeal 	    id->ident_length));
364161dfa509SRick McNeal 	ks_nm[id->ident_length] = '\0';
364261dfa509SRick McNeal 	cmn_err(CE_WARN, "STMF: remote port kstat creation failed: %s", ks_nm);
364361dfa509SRick McNeal }
364461dfa509SRick McNeal 
364561dfa509SRick McNeal static void
stmf_destroy_kstat_rport(stmf_i_remote_port_t * irport)364661dfa509SRick McNeal stmf_destroy_kstat_rport(stmf_i_remote_port_t *irport)
364761dfa509SRick McNeal {
364861dfa509SRick McNeal 	if (irport->irport_kstat_io != NULL) {
364961dfa509SRick McNeal 		kstat_delete(irport->irport_kstat_io);
365061dfa509SRick McNeal 	}
365161dfa509SRick McNeal 	if (irport->irport_kstat_estat != NULL) {
365261dfa509SRick McNeal 		kstat_delete(irport->irport_kstat_estat);
365361dfa509SRick McNeal 	}
365461dfa509SRick McNeal 	if (irport->irport_kstat_info != NULL) {
365561dfa509SRick McNeal 		stmf_kstat_rport_info_t *ks_info;
365661dfa509SRick McNeal 		kstat_named_t *knp;
365761dfa509SRick McNeal 		void *ptr;
365861dfa509SRick McNeal 		int i;
365961dfa509SRick McNeal 
366061dfa509SRick McNeal 		ks_info = (stmf_kstat_rport_info_t *)KSTAT_NAMED_PTR(
366161dfa509SRick McNeal 		    irport->irport_kstat_info);
366261dfa509SRick McNeal 		kstat_delete(irport->irport_kstat_info);
366361dfa509SRick McNeal 		ptr = KSTAT_NAMED_STR_PTR(&ks_info->i_rport_name);
366461dfa509SRick McNeal 		kmem_free(ptr, KSTAT_NAMED_STR_BUFLEN(&ks_info->i_rport_name));
366561dfa509SRick McNeal 
366661dfa509SRick McNeal 		for (i = 0, knp = ks_info->i_rport_uinfo;
366761dfa509SRick McNeal 		    i < STMF_RPORT_INFO_LIMIT; i++, knp++) {
366861dfa509SRick McNeal 			ptr = KSTAT_NAMED_STR_PTR(knp);
366961dfa509SRick McNeal 			if (ptr != NULL)
367061dfa509SRick McNeal 			kmem_free(ptr, KSTAT_NAMED_STR_BUFLEN(knp));
367161dfa509SRick McNeal 		}
367261dfa509SRick McNeal 		kmem_free(ks_info, sizeof (*ks_info));
367361dfa509SRick McNeal 	}
367461dfa509SRick McNeal }
367561dfa509SRick McNeal 
3676427fcaf8Stim szeto static stmf_i_remote_port_t *
stmf_irport_register(scsi_devid_desc_t * rport_devid)3677427fcaf8Stim szeto stmf_irport_register(scsi_devid_desc_t *rport_devid)
3678427fcaf8Stim szeto {
3679427fcaf8Stim szeto 	stmf_i_remote_port_t	*irport;
3680427fcaf8Stim szeto 
3681427fcaf8Stim szeto 	mutex_enter(&stmf_state.stmf_lock);
3682427fcaf8Stim szeto 
3683427fcaf8Stim szeto 	/*
3684427fcaf8Stim szeto 	 * Lookup will bump the refcnt if there's an existing rport
3685427fcaf8Stim szeto 	 * context for this identifier.
3686427fcaf8Stim szeto 	 */
3687427fcaf8Stim szeto 	if ((irport = stmf_irport_lookup_locked(rport_devid)) != NULL) {
3688427fcaf8Stim szeto 		mutex_exit(&stmf_state.stmf_lock);
3689427fcaf8Stim szeto 		return (irport);
3690427fcaf8Stim szeto 	}
3691427fcaf8Stim szeto 
3692427fcaf8Stim szeto 	irport = stmf_irport_create(rport_devid);
3693427fcaf8Stim szeto 	if (irport == NULL) {
3694427fcaf8Stim szeto 		mutex_exit(&stmf_state.stmf_lock);
3695427fcaf8Stim szeto 		return (NULL);
3696427fcaf8Stim szeto 	}
3697427fcaf8Stim szeto 
369861dfa509SRick McNeal 	stmf_create_kstat_rport(irport);
3699427fcaf8Stim szeto 	avl_add(&stmf_state.stmf_irportlist, irport);
3700427fcaf8Stim szeto 	mutex_exit(&stmf_state.stmf_lock);
3701427fcaf8Stim szeto 
3702427fcaf8Stim szeto 	return (irport);
3703427fcaf8Stim szeto }
3704427fcaf8Stim szeto 
3705427fcaf8Stim szeto static stmf_i_remote_port_t *
stmf_irport_lookup_locked(scsi_devid_desc_t * rport_devid)3706427fcaf8Stim szeto stmf_irport_lookup_locked(scsi_devid_desc_t *rport_devid)
3707427fcaf8Stim szeto {
3708427fcaf8Stim szeto 	stmf_i_remote_port_t	*irport;
3709427fcaf8Stim szeto 	stmf_i_remote_port_t	tmp_irport;
3710427fcaf8Stim szeto 
3711427fcaf8Stim szeto 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3712427fcaf8Stim szeto 	tmp_irport.irport_id = rport_devid;
3713427fcaf8Stim szeto 	irport = avl_find(&stmf_state.stmf_irportlist, &tmp_irport, NULL);
3714427fcaf8Stim szeto 	if (irport != NULL) {
3715427fcaf8Stim szeto 		mutex_enter(&irport->irport_mutex);
3716427fcaf8Stim szeto 		irport->irport_refcnt++;
3717427fcaf8Stim szeto 		mutex_exit(&irport->irport_mutex);
3718427fcaf8Stim szeto 	}
3719427fcaf8Stim szeto 
3720427fcaf8Stim szeto 	return (irport);
3721427fcaf8Stim szeto }
3722427fcaf8Stim szeto 
3723427fcaf8Stim szeto static void
stmf_irport_deregister(stmf_i_remote_port_t * irport)3724427fcaf8Stim szeto stmf_irport_deregister(stmf_i_remote_port_t *irport)
3725427fcaf8Stim szeto {
3726427fcaf8Stim szeto 	/*
3727427fcaf8Stim szeto 	 * If we were actually going to remove unreferenced remote ports
3728427fcaf8Stim szeto 	 * we would want to acquire stmf_state.stmf_lock before getting
3729427fcaf8Stim szeto 	 * the irport mutex.
3730427fcaf8Stim szeto 	 *
3731427fcaf8Stim szeto 	 * Instead we're just going to leave it there even if unreferenced.
3732427fcaf8Stim szeto 	 */
3733427fcaf8Stim szeto 	mutex_enter(&irport->irport_mutex);
3734427fcaf8Stim szeto 	irport->irport_refcnt--;
3735427fcaf8Stim szeto 	mutex_exit(&irport->irport_mutex);
3736427fcaf8Stim szeto }
3737427fcaf8Stim szeto 
3738427fcaf8Stim szeto /*
3739fcf3ce44SJohn Forte  * Port provider has to make sure that register/deregister session and
3740fcf3ce44SJohn Forte  * port are serialized calls.
3741fcf3ce44SJohn Forte  */
3742fcf3ce44SJohn Forte stmf_status_t
stmf_register_scsi_session(stmf_local_port_t * lport,stmf_scsi_session_t * ss)3743fcf3ce44SJohn Forte stmf_register_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss)
3744fcf3ce44SJohn Forte {
3745fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
3746fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport = (stmf_i_local_port_t *)
3747fcf3ce44SJohn Forte 	    lport->lport_stmf_private;
3748fcf3ce44SJohn Forte 	uint8_t		lun[8];
3749fcf3ce44SJohn Forte 
3750fcf3ce44SJohn Forte 	/*
3751fcf3ce44SJohn Forte 	 * Port state has to be online to register a scsi session. It is
3752fcf3ce44SJohn Forte 	 * possible that we started an offline operation and a new SCSI
3753fcf3ce44SJohn Forte 	 * session started at the same time (in that case also we are going
3754fcf3ce44SJohn Forte 	 * to fail the registeration). But any other state is simply
3755fcf3ce44SJohn Forte 	 * a bad port provider implementation.
3756fcf3ce44SJohn Forte 	 */
3757fcf3ce44SJohn Forte 	if (ilport->ilport_state != STMF_STATE_ONLINE) {
3758fcf3ce44SJohn Forte 		if (ilport->ilport_state != STMF_STATE_OFFLINING) {
3759fcf3ce44SJohn Forte 			stmf_trace(lport->lport_alias, "Port is trying to "
3760fcf3ce44SJohn Forte 			    "register a session while the state is neither "
3761fcf3ce44SJohn Forte 			    "online nor offlining");
3762fcf3ce44SJohn Forte 		}
3763fcf3ce44SJohn Forte 		return (STMF_FAILURE);
3764fcf3ce44SJohn Forte 	}
3765fcf3ce44SJohn Forte 	bzero(lun, 8);
3766fcf3ce44SJohn Forte 	iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3767427fcaf8Stim szeto 	if ((iss->iss_irport = stmf_irport_register(ss->ss_rport_id)) == NULL) {
3768427fcaf8Stim szeto 		stmf_trace(lport->lport_alias, "Could not register "
3769427fcaf8Stim szeto 		    "remote port during session registration");
3770427fcaf8Stim szeto 		return (STMF_FAILURE);
3771427fcaf8Stim szeto 	}
3772427fcaf8Stim szeto 
3773fcf3ce44SJohn Forte 	iss->iss_flags |= ISS_BEING_CREATED;
3774fcf3ce44SJohn Forte 
3775716c1805SNattuvetty Bhavyan 	if (ss->ss_rport == NULL) {
3776716c1805SNattuvetty Bhavyan 		iss->iss_flags |= ISS_NULL_TPTID;
3777716c1805SNattuvetty Bhavyan 		ss->ss_rport = stmf_scsilib_devid_to_remote_port(
3778716c1805SNattuvetty Bhavyan 		    ss->ss_rport_id);
3779716c1805SNattuvetty Bhavyan 		if (ss->ss_rport == NULL) {
3780716c1805SNattuvetty Bhavyan 			iss->iss_flags &= ~(ISS_NULL_TPTID | ISS_BEING_CREATED);
3781716c1805SNattuvetty Bhavyan 			stmf_trace(lport->lport_alias, "Device id to "
3782716c1805SNattuvetty Bhavyan 			    "remote port conversion failed");
3783716c1805SNattuvetty Bhavyan 			return (STMF_FAILURE);
3784716c1805SNattuvetty Bhavyan 		}
3785716c1805SNattuvetty Bhavyan 	} else {
3786716c1805SNattuvetty Bhavyan 		if (!stmf_scsilib_tptid_validate(ss->ss_rport->rport_tptid,
3787716c1805SNattuvetty Bhavyan 		    ss->ss_rport->rport_tptid_sz, NULL)) {
3788716c1805SNattuvetty Bhavyan 			iss->iss_flags &= ~ISS_BEING_CREATED;
3789716c1805SNattuvetty Bhavyan 			stmf_trace(lport->lport_alias, "Remote port "
3790716c1805SNattuvetty Bhavyan 			    "transport id validation failed");
3791716c1805SNattuvetty Bhavyan 			return (STMF_FAILURE);
3792716c1805SNattuvetty Bhavyan 		}
3793716c1805SNattuvetty Bhavyan 	}
3794716c1805SNattuvetty Bhavyan 
3795fcf3ce44SJohn Forte 	/* sessions use the ilport_lock. No separate lock is required */
3796fcf3ce44SJohn Forte 	iss->iss_lockp = &ilport->ilport_lock;
3797fcf3ce44SJohn Forte 
3798780c822cStim szeto 	if (iss->iss_sm != NULL)
3799780c822cStim szeto 		cmn_err(CE_PANIC, "create lun map called with non NULL map");
3800780c822cStim szeto 	iss->iss_sm = (stmf_lun_map_t *)kmem_zalloc(sizeof (stmf_lun_map_t),
3801780c822cStim szeto 	    KM_SLEEP);
3802780c822cStim szeto 
3803780c822cStim szeto 	mutex_enter(&stmf_state.stmf_lock);
3804fcf3ce44SJohn Forte 	rw_enter(&ilport->ilport_lock, RW_WRITER);
3805780c822cStim szeto 	(void) stmf_session_create_lun_map(ilport, iss);
3806fcf3ce44SJohn Forte 	ilport->ilport_nsessions++;
3807fcf3ce44SJohn Forte 	iss->iss_next = ilport->ilport_ss_list;
3808fcf3ce44SJohn Forte 	ilport->ilport_ss_list = iss;
3809fcf3ce44SJohn Forte 	rw_exit(&ilport->ilport_lock);
3810780c822cStim szeto 	mutex_exit(&stmf_state.stmf_lock);
3811fcf3ce44SJohn Forte 
3812fcf3ce44SJohn Forte 	iss->iss_creation_time = ddi_get_time();
38131a5e258fSJosef 'Jeff' Sipek 	ss->ss_session_id = atomic_inc_64_nv(&stmf_session_counter);
3814fcf3ce44SJohn Forte 	iss->iss_flags &= ~ISS_BEING_CREATED;
381545039663SJohn Forte 	/* XXX should we remove ISS_LUN_INVENTORY_CHANGED on new session? */
381645039663SJohn Forte 	iss->iss_flags &= ~ISS_LUN_INVENTORY_CHANGED;
3817e17f3b22Stim szeto 	DTRACE_PROBE2(session__online, stmf_local_port_t *, lport,
3818e17f3b22Stim szeto 	    stmf_scsi_session_t *, ss);
3819fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
3820fcf3ce44SJohn Forte }
3821fcf3ce44SJohn Forte 
382261dfa509SRick McNeal stmf_status_t
stmf_add_rport_info(stmf_scsi_session_t * ss,const char * prop_name,const char * prop_value)382361dfa509SRick McNeal stmf_add_rport_info(stmf_scsi_session_t *ss,
382461dfa509SRick McNeal     const char *prop_name, const char *prop_value)
382561dfa509SRick McNeal {
382661dfa509SRick McNeal 	stmf_i_scsi_session_t *iss = ss->ss_stmf_private;
382761dfa509SRick McNeal 	stmf_i_remote_port_t *irport = iss->iss_irport;
382861dfa509SRick McNeal 	kstat_named_t *knp;
382961dfa509SRick McNeal 	char *s;
383061dfa509SRick McNeal 	int i;
383161dfa509SRick McNeal 
383261dfa509SRick McNeal 	s = strdup(prop_value);
383361dfa509SRick McNeal 
383461dfa509SRick McNeal 	mutex_enter(irport->irport_kstat_info->ks_lock);
383561dfa509SRick McNeal 	/* Make sure the caller doesn't try to add already existing property */
383661dfa509SRick McNeal 	knp = KSTAT_NAMED_PTR(irport->irport_kstat_info);
383761dfa509SRick McNeal 	for (i = 0; i < STMF_KSTAT_RPORT_DATAMAX; i++, knp++) {
383861dfa509SRick McNeal 		if (KSTAT_NAMED_STR_PTR(knp) == NULL)
383961dfa509SRick McNeal 			break;
384061dfa509SRick McNeal 
384161dfa509SRick McNeal 		ASSERT(strcmp(knp->name, prop_name) != 0);
384261dfa509SRick McNeal 	}
384361dfa509SRick McNeal 
384461dfa509SRick McNeal 	if (i == STMF_KSTAT_RPORT_DATAMAX) {
384561dfa509SRick McNeal 		mutex_exit(irport->irport_kstat_info->ks_lock);
384661dfa509SRick McNeal 		kmem_free(s, strlen(s) + 1);
384761dfa509SRick McNeal 		return (STMF_FAILURE);
384861dfa509SRick McNeal 	}
384961dfa509SRick McNeal 
385061dfa509SRick McNeal 	irport->irport_info_dirty = B_TRUE;
385161dfa509SRick McNeal 	kstat_named_init(knp, prop_name, KSTAT_DATA_STRING);
385261dfa509SRick McNeal 	kstat_named_setstr(knp, s);
385361dfa509SRick McNeal 	mutex_exit(irport->irport_kstat_info->ks_lock);
385461dfa509SRick McNeal 
385561dfa509SRick McNeal 	return (STMF_SUCCESS);
385661dfa509SRick McNeal }
385761dfa509SRick McNeal 
385861dfa509SRick McNeal void
stmf_remove_rport_info(stmf_scsi_session_t * ss,const char * prop_name)385961dfa509SRick McNeal stmf_remove_rport_info(stmf_scsi_session_t *ss,
386061dfa509SRick McNeal     const char *prop_name)
386161dfa509SRick McNeal {
386261dfa509SRick McNeal 	stmf_i_scsi_session_t *iss = ss->ss_stmf_private;
386361dfa509SRick McNeal 	stmf_i_remote_port_t *irport = iss->iss_irport;
386461dfa509SRick McNeal 	kstat_named_t *knp;
386561dfa509SRick McNeal 	char *s;
386661dfa509SRick McNeal 	int i;
386761dfa509SRick McNeal 	uint32_t len;
386861dfa509SRick McNeal 
386961dfa509SRick McNeal 	mutex_enter(irport->irport_kstat_info->ks_lock);
387061dfa509SRick McNeal 	knp = KSTAT_NAMED_PTR(irport->irport_kstat_info);
387161dfa509SRick McNeal 	for (i = 0; i < STMF_KSTAT_RPORT_DATAMAX; i++, knp++) {
3872*ae127fcdSToomas Soome 		if (strcmp(knp->name, prop_name) == 0)
387361dfa509SRick McNeal 			break;
387461dfa509SRick McNeal 	}
387561dfa509SRick McNeal 
387661dfa509SRick McNeal 	if (i == STMF_KSTAT_RPORT_DATAMAX) {
387761dfa509SRick McNeal 		mutex_exit(irport->irport_kstat_info->ks_lock);
387861dfa509SRick McNeal 		return;
387961dfa509SRick McNeal 	}
388061dfa509SRick McNeal 
388161dfa509SRick McNeal 	s = KSTAT_NAMED_STR_PTR(knp);
388261dfa509SRick McNeal 	len = KSTAT_NAMED_STR_BUFLEN(knp);
388361dfa509SRick McNeal 
388461dfa509SRick McNeal 	for (; i < STMF_KSTAT_RPORT_DATAMAX - 1; i++, knp++) {
388561dfa509SRick McNeal 		kstat_named_init(knp, knp[1].name, KSTAT_DATA_STRING);
388661dfa509SRick McNeal 		kstat_named_setstr(knp, KSTAT_NAMED_STR_PTR(&knp[1]));
388761dfa509SRick McNeal 	}
388861dfa509SRick McNeal 	kstat_named_init(knp, "", KSTAT_DATA_STRING);
388961dfa509SRick McNeal 
389061dfa509SRick McNeal 	irport->irport_info_dirty = B_TRUE;
389161dfa509SRick McNeal 	mutex_exit(irport->irport_kstat_info->ks_lock);
389261dfa509SRick McNeal 	kmem_free(s, len);
389361dfa509SRick McNeal }
389461dfa509SRick McNeal 
389561dfa509SRick McNeal static int
stmf_kstat_rport_update(kstat_t * ksp,int rw)389661dfa509SRick McNeal stmf_kstat_rport_update(kstat_t *ksp, int rw)
389761dfa509SRick McNeal {
389861dfa509SRick McNeal 	stmf_i_remote_port_t *irport = ksp->ks_private;
389961dfa509SRick McNeal 	kstat_named_t *knp;
390061dfa509SRick McNeal 	uint_t ndata = 0;
390161dfa509SRick McNeal 	size_t dsize = 0;
390261dfa509SRick McNeal 	int i;
390361dfa509SRick McNeal 
390461dfa509SRick McNeal 	if (rw == KSTAT_WRITE)
390561dfa509SRick McNeal 		return (EACCES);
390661dfa509SRick McNeal 
390761dfa509SRick McNeal 	if (!irport->irport_info_dirty)
390861dfa509SRick McNeal 		return (0);
390961dfa509SRick McNeal 
391061dfa509SRick McNeal 	knp = KSTAT_NAMED_PTR(ksp);
391161dfa509SRick McNeal 	for (i = 0; i < STMF_KSTAT_RPORT_DATAMAX; i++, knp++) {
391261dfa509SRick McNeal 		if (KSTAT_NAMED_STR_PTR(knp) == NULL)
391361dfa509SRick McNeal 			break;
391461dfa509SRick McNeal 		ndata++;
391561dfa509SRick McNeal 		dsize += KSTAT_NAMED_STR_BUFLEN(knp);
391661dfa509SRick McNeal 	}
391761dfa509SRick McNeal 
391861dfa509SRick McNeal 	ksp->ks_ndata = ndata;
391961dfa509SRick McNeal 	ksp->ks_data_size = sizeof (kstat_named_t) * ndata + dsize;
392061dfa509SRick McNeal 	irport->irport_info_dirty = B_FALSE;
392161dfa509SRick McNeal 
392261dfa509SRick McNeal 	return (0);
392361dfa509SRick McNeal }
392461dfa509SRick McNeal 
3925fcf3ce44SJohn Forte void
stmf_deregister_scsi_session(stmf_local_port_t * lport,stmf_scsi_session_t * ss)3926fcf3ce44SJohn Forte stmf_deregister_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss)
3927fcf3ce44SJohn Forte {
3928fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport = (stmf_i_local_port_t *)
3929fcf3ce44SJohn Forte 	    lport->lport_stmf_private;
3930fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss, **ppss;
3931fcf3ce44SJohn Forte 	int found = 0;
393245039663SJohn Forte 	stmf_ic_msg_t *ic_session_dereg;
393345039663SJohn Forte 	stmf_status_t ic_ret = STMF_FAILURE;
393461dfa509SRick McNeal 	stmf_lun_map_t *sm;
393561dfa509SRick McNeal 	stmf_i_lu_t *ilu;
393661dfa509SRick McNeal 	uint16_t n;
393761dfa509SRick McNeal 	stmf_lun_map_ent_t *ent;
3938fcf3ce44SJohn Forte 
3939e17f3b22Stim szeto 	DTRACE_PROBE2(session__offline, stmf_local_port_t *, lport,
3940e17f3b22Stim szeto 	    stmf_scsi_session_t *, ss);
3941e17f3b22Stim szeto 
3942fcf3ce44SJohn Forte 	iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3943fcf3ce44SJohn Forte 	if (ss->ss_rport_alias) {
3944fcf3ce44SJohn Forte 		ss->ss_rport_alias = NULL;
3945fcf3ce44SJohn Forte 	}
3946fcf3ce44SJohn Forte 
3947fcf3ce44SJohn Forte try_dereg_ss_again:
3948fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
3949fcf3ce44SJohn Forte 	atomic_and_32(&iss->iss_flags,
3950fcf3ce44SJohn Forte 	    ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS));
3951fcf3ce44SJohn Forte 	if (iss->iss_flags & ISS_EVENT_ACTIVE) {
3952fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
3953fcf3ce44SJohn Forte 		delay(1);
3954fcf3ce44SJohn Forte 		goto try_dereg_ss_again;
3955fcf3ce44SJohn Forte 	}
395645039663SJohn Forte 
395745039663SJohn Forte 	/* dereg proxy session if not standby port */
3958cd36db67SJohn Forte 	if (stmf_state.stmf_alua_state == 1 &&
3959cd36db67SJohn Forte 	    ilport->ilport_standby == 0 &&
3960cd36db67SJohn Forte 	    ilport->ilport_alua == 1) {
396145039663SJohn Forte 		ic_session_dereg = ic_session_dereg_msg_alloc(
396245039663SJohn Forte 		    ss, stmf_proxy_msg_id);
396345039663SJohn Forte 		if (ic_session_dereg) {
396445039663SJohn Forte 			ic_ret = ic_tx_msg(ic_session_dereg);
396545039663SJohn Forte 			if (ic_ret == STMF_IC_MSG_SUCCESS) {
396645039663SJohn Forte 				stmf_proxy_msg_id++;
396745039663SJohn Forte 			}
396845039663SJohn Forte 		}
396945039663SJohn Forte 	}
397045039663SJohn Forte 
3971fcf3ce44SJohn Forte 	rw_enter(&ilport->ilport_lock, RW_WRITER);
3972fcf3ce44SJohn Forte 	for (ppss = &ilport->ilport_ss_list; *ppss != NULL;
3973fcf3ce44SJohn Forte 	    ppss = &((*ppss)->iss_next)) {
3974fcf3ce44SJohn Forte 		if (iss == (*ppss)) {
3975fcf3ce44SJohn Forte 			*ppss = (*ppss)->iss_next;
3976fcf3ce44SJohn Forte 			found = 1;
3977fcf3ce44SJohn Forte 			break;
3978fcf3ce44SJohn Forte 		}
3979fcf3ce44SJohn Forte 	}
3980fcf3ce44SJohn Forte 	if (!found) {
3981fcf3ce44SJohn Forte 		cmn_err(CE_PANIC, "Deregister session called for non existent"
3982fcf3ce44SJohn Forte 		    " session");
3983fcf3ce44SJohn Forte 	}
3984fcf3ce44SJohn Forte 	ilport->ilport_nsessions--;
3985fcf3ce44SJohn Forte 
3986427fcaf8Stim szeto 	stmf_irport_deregister(iss->iss_irport);
398761dfa509SRick McNeal 	/*
398861dfa509SRick McNeal 	 * to avoid conflict with updating session's map,
398961dfa509SRick McNeal 	 * which only grab stmf_lock
399061dfa509SRick McNeal 	 */
399161dfa509SRick McNeal 	sm = iss->iss_sm;
399261dfa509SRick McNeal 	iss->iss_sm = NULL;
399361dfa509SRick McNeal 	iss->iss_hg = NULL;
399461dfa509SRick McNeal 
3995780c822cStim szeto 	rw_exit(&ilport->ilport_lock);
399661dfa509SRick McNeal 
399761dfa509SRick McNeal 	if (sm->lm_nentries) {
399861dfa509SRick McNeal 		for (n = 0; n < sm->lm_nentries; n++) {
399961dfa509SRick McNeal 			if ((ent = (stmf_lun_map_ent_t *)sm->lm_plus[n])
400061dfa509SRick McNeal 			    != NULL) {
400161dfa509SRick McNeal 				if (ent->ent_itl_datap) {
400261dfa509SRick McNeal 					stmf_do_itl_dereg(ent->ent_lu,
400361dfa509SRick McNeal 					    ent->ent_itl_datap,
400461dfa509SRick McNeal 					    STMF_ITL_REASON_IT_NEXUS_LOSS);
400561dfa509SRick McNeal 				}
400661dfa509SRick McNeal 				ilu = (stmf_i_lu_t *)
400761dfa509SRick McNeal 				    ent->ent_lu->lu_stmf_private;
400861dfa509SRick McNeal 				atomic_dec_32(&ilu->ilu_ref_cnt);
400961dfa509SRick McNeal 				kmem_free(sm->lm_plus[n],
401061dfa509SRick McNeal 				    sizeof (stmf_lun_map_ent_t));
401161dfa509SRick McNeal 			}
401261dfa509SRick McNeal 		}
401361dfa509SRick McNeal 		kmem_free(sm->lm_plus,
401461dfa509SRick McNeal 		    sizeof (stmf_lun_map_ent_t *) * sm->lm_nentries);
401561dfa509SRick McNeal 	}
401661dfa509SRick McNeal 	kmem_free(sm, sizeof (*sm));
4017716c1805SNattuvetty Bhavyan 
4018716c1805SNattuvetty Bhavyan 	if (iss->iss_flags & ISS_NULL_TPTID) {
4019716c1805SNattuvetty Bhavyan 		stmf_remote_port_free(ss->ss_rport);
4020716c1805SNattuvetty Bhavyan 	}
402161dfa509SRick McNeal 
402261dfa509SRick McNeal 	mutex_exit(&stmf_state.stmf_lock);
4023fcf3ce44SJohn Forte }
4024fcf3ce44SJohn Forte 
402561dfa509SRick McNeal 
402661dfa509SRick McNeal 
4027fcf3ce44SJohn Forte stmf_i_scsi_session_t *
stmf_session_id_to_issptr(uint64_t session_id,int stay_locked)4028fcf3ce44SJohn Forte stmf_session_id_to_issptr(uint64_t session_id, int stay_locked)
4029fcf3ce44SJohn Forte {
4030fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
4031fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
4032fcf3ce44SJohn Forte 
4033fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
4034fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
4035fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
4036fcf3ce44SJohn Forte 		rw_enter(&ilport->ilport_lock, RW_WRITER);
4037fcf3ce44SJohn Forte 		for (iss = ilport->ilport_ss_list; iss != NULL;
4038fcf3ce44SJohn Forte 		    iss = iss->iss_next) {
4039fcf3ce44SJohn Forte 			if (iss->iss_ss->ss_session_id == session_id) {
4040fcf3ce44SJohn Forte 				if (!stay_locked)
4041fcf3ce44SJohn Forte 					rw_exit(&ilport->ilport_lock);
4042fcf3ce44SJohn Forte 				mutex_exit(&stmf_state.stmf_lock);
4043fcf3ce44SJohn Forte 				return (iss);
4044fcf3ce44SJohn Forte 			}
4045fcf3ce44SJohn Forte 		}
4046fcf3ce44SJohn Forte 		rw_exit(&ilport->ilport_lock);
4047fcf3ce44SJohn Forte 	}
4048fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
4049fcf3ce44SJohn Forte 	return (NULL);
4050fcf3ce44SJohn Forte }
4051fcf3ce44SJohn Forte 
4052fcf3ce44SJohn Forte void
stmf_release_itl_handle(stmf_lu_t * lu,stmf_itl_data_t * itl)4053fcf3ce44SJohn Forte stmf_release_itl_handle(stmf_lu_t *lu, stmf_itl_data_t *itl)
4054fcf3ce44SJohn Forte {
4055fcf3ce44SJohn Forte 	stmf_itl_data_t **itlpp;
4056fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
4057fcf3ce44SJohn Forte 
4058fcf3ce44SJohn Forte 	ASSERT(itl->itl_flags & STMF_ITL_BEING_TERMINATED);
4059fcf3ce44SJohn Forte 
4060fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4061fcf3ce44SJohn Forte 	mutex_enter(&ilu->ilu_task_lock);
4062fcf3ce44SJohn Forte 	for (itlpp = &ilu->ilu_itl_list; (*itlpp) != NULL;
4063fcf3ce44SJohn Forte 	    itlpp = &(*itlpp)->itl_next) {
4064fcf3ce44SJohn Forte 		if ((*itlpp) == itl)
4065fcf3ce44SJohn Forte 			break;
4066fcf3ce44SJohn Forte 	}
4067fcf3ce44SJohn Forte 	ASSERT((*itlpp) != NULL);
4068fcf3ce44SJohn Forte 	*itlpp = itl->itl_next;
4069fcf3ce44SJohn Forte 	mutex_exit(&ilu->ilu_task_lock);
4070fcf3ce44SJohn Forte 	lu->lu_abort(lu, STMF_LU_ITL_HANDLE_REMOVED, itl->itl_handle,
4071fcf3ce44SJohn Forte 	    (uint32_t)itl->itl_hdlrm_reason);
4072427fcaf8Stim szeto 
4073fcf3ce44SJohn Forte 	kmem_free(itl, sizeof (*itl));
4074fcf3ce44SJohn Forte }
4075fcf3ce44SJohn Forte 
4076fcf3ce44SJohn Forte stmf_status_t
stmf_register_itl_handle(stmf_lu_t * lu,uint8_t * lun,stmf_scsi_session_t * ss,uint64_t session_id,void * itl_handle)4077fcf3ce44SJohn Forte stmf_register_itl_handle(stmf_lu_t *lu, uint8_t *lun,
4078fcf3ce44SJohn Forte     stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle)
4079fcf3ce44SJohn Forte {
4080fcf3ce44SJohn Forte 	stmf_itl_data_t *itl;
4081fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
4082fcf3ce44SJohn Forte 	stmf_lun_map_ent_t *lun_map_ent;
4083fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
4084fcf3ce44SJohn Forte 	uint16_t n;
4085fcf3ce44SJohn Forte 
4086fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4087fcf3ce44SJohn Forte 	if (ss == NULL) {
4088fcf3ce44SJohn Forte 		iss = stmf_session_id_to_issptr(session_id, 1);
4089fcf3ce44SJohn Forte 		if (iss == NULL)
4090fcf3ce44SJohn Forte 			return (STMF_NOT_FOUND);
4091fcf3ce44SJohn Forte 	} else {
4092fcf3ce44SJohn Forte 		iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4093fcf3ce44SJohn Forte 	}
4094fcf3ce44SJohn Forte 
4095a8e2ef8fStim szeto 	mutex_enter(&stmf_state.stmf_lock);
4096427fcaf8Stim szeto 	rw_enter(iss->iss_lockp, RW_WRITER);
4097fcf3ce44SJohn Forte 	n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4098fcf3ce44SJohn Forte 	lun_map_ent = (stmf_lun_map_ent_t *)
4099fcf3ce44SJohn Forte 	    stmf_get_ent_from_map(iss->iss_sm, n);
4100fcf3ce44SJohn Forte 	if ((lun_map_ent == NULL) || (lun_map_ent->ent_lu != lu)) {
4101fcf3ce44SJohn Forte 		rw_exit(iss->iss_lockp);
4102a8e2ef8fStim szeto 		mutex_exit(&stmf_state.stmf_lock);
4103fcf3ce44SJohn Forte 		return (STMF_NOT_FOUND);
4104fcf3ce44SJohn Forte 	}
4105fcf3ce44SJohn Forte 	if (lun_map_ent->ent_itl_datap != NULL) {
4106fcf3ce44SJohn Forte 		rw_exit(iss->iss_lockp);
4107a8e2ef8fStim szeto 		mutex_exit(&stmf_state.stmf_lock);
4108fcf3ce44SJohn Forte 		return (STMF_ALREADY);
4109fcf3ce44SJohn Forte 	}
4110fcf3ce44SJohn Forte 
4111fcf3ce44SJohn Forte 	itl = (stmf_itl_data_t *)kmem_zalloc(sizeof (*itl), KM_NOSLEEP);
4112fcf3ce44SJohn Forte 	if (itl == NULL) {
4113fcf3ce44SJohn Forte 		rw_exit(iss->iss_lockp);
4114a8e2ef8fStim szeto 		mutex_exit(&stmf_state.stmf_lock);
4115fcf3ce44SJohn Forte 		return (STMF_ALLOC_FAILURE);
4116fcf3ce44SJohn Forte 	}
4117fcf3ce44SJohn Forte 
4118427fcaf8Stim szeto 	itl->itl_ilu = ilu;
4119427fcaf8Stim szeto 	itl->itl_session = iss;
4120fcf3ce44SJohn Forte 	itl->itl_counter = 1;
4121fcf3ce44SJohn Forte 	itl->itl_lun = n;
4122fcf3ce44SJohn Forte 	itl->itl_handle = itl_handle;
4123427fcaf8Stim szeto 
4124fcf3ce44SJohn Forte 	mutex_enter(&ilu->ilu_task_lock);
4125fcf3ce44SJohn Forte 	itl->itl_next = ilu->ilu_itl_list;
4126fcf3ce44SJohn Forte 	ilu->ilu_itl_list = itl;
4127fcf3ce44SJohn Forte 	mutex_exit(&ilu->ilu_task_lock);
4128fcf3ce44SJohn Forte 	lun_map_ent->ent_itl_datap = itl;
4129fcf3ce44SJohn Forte 	rw_exit(iss->iss_lockp);
4130a8e2ef8fStim szeto 	mutex_exit(&stmf_state.stmf_lock);
4131fcf3ce44SJohn Forte 
4132fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
4133fcf3ce44SJohn Forte }
4134fcf3ce44SJohn Forte 
4135fcf3ce44SJohn Forte void
stmf_do_itl_dereg(stmf_lu_t * lu,stmf_itl_data_t * itl,uint8_t hdlrm_reason)4136fcf3ce44SJohn Forte stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl, uint8_t hdlrm_reason)
4137fcf3ce44SJohn Forte {
4138fcf3ce44SJohn Forte 	uint8_t old, new;
4139fcf3ce44SJohn Forte 
4140fcf3ce44SJohn Forte 	do {
4141fcf3ce44SJohn Forte 		old = new = itl->itl_flags;
4142fcf3ce44SJohn Forte 		if (old & STMF_ITL_BEING_TERMINATED)
4143fcf3ce44SJohn Forte 			return;
4144fcf3ce44SJohn Forte 		new |= STMF_ITL_BEING_TERMINATED;
4145fcf3ce44SJohn Forte 	} while (atomic_cas_8(&itl->itl_flags, old, new) != old);
4146fcf3ce44SJohn Forte 	itl->itl_hdlrm_reason = hdlrm_reason;
4147fcf3ce44SJohn Forte 
4148fcf3ce44SJohn Forte 	ASSERT(itl->itl_counter);
4149fcf3ce44SJohn Forte 
41501a5e258fSJosef 'Jeff' Sipek 	if (atomic_dec_32_nv(&itl->itl_counter))
4151fcf3ce44SJohn Forte 		return;
4152fcf3ce44SJohn Forte 
4153fcf3ce44SJohn Forte 	stmf_release_itl_handle(lu, itl);
4154fcf3ce44SJohn Forte }
4155fcf3ce44SJohn Forte 
4156fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_all_lu_itl_handles(stmf_lu_t * lu)4157fcf3ce44SJohn Forte stmf_deregister_all_lu_itl_handles(stmf_lu_t *lu)
4158fcf3ce44SJohn Forte {
4159fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
4160fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
4161fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
4162fcf3ce44SJohn Forte 	stmf_lun_map_t *lm;
4163fcf3ce44SJohn Forte 	stmf_lun_map_ent_t *ent;
4164fcf3ce44SJohn Forte 	uint32_t nmaps, nu;
4165fcf3ce44SJohn Forte 	stmf_itl_data_t **itl_list;
4166fcf3ce44SJohn Forte 	int i;
4167fcf3ce44SJohn Forte 
4168fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4169fcf3ce44SJohn Forte 
4170fcf3ce44SJohn Forte dereg_itl_start:;
4171fcf3ce44SJohn Forte 	nmaps = ilu->ilu_ref_cnt;
4172fcf3ce44SJohn Forte 	if (nmaps == 0)
4173fcf3ce44SJohn Forte 		return (STMF_NOT_FOUND);
4174fcf3ce44SJohn Forte 	itl_list = (stmf_itl_data_t **)kmem_zalloc(
4175fcf3ce44SJohn Forte 	    nmaps * sizeof (stmf_itl_data_t *), KM_SLEEP);
4176fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
4177fcf3ce44SJohn Forte 	if (nmaps != ilu->ilu_ref_cnt) {
4178fcf3ce44SJohn Forte 		/* Something changed, start all over */
4179fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
4180fcf3ce44SJohn Forte 		kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
4181fcf3ce44SJohn Forte 		goto dereg_itl_start;
4182fcf3ce44SJohn Forte 	}
4183fcf3ce44SJohn Forte 	nu = 0;
4184fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
4185fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
4186fcf3ce44SJohn Forte 		rw_enter(&ilport->ilport_lock, RW_WRITER);
4187fcf3ce44SJohn Forte 		for (iss = ilport->ilport_ss_list; iss != NULL;
4188fcf3ce44SJohn Forte 		    iss = iss->iss_next) {
4189fcf3ce44SJohn Forte 			lm = iss->iss_sm;
4190fcf3ce44SJohn Forte 			if (!lm)
4191fcf3ce44SJohn Forte 				continue;
4192fcf3ce44SJohn Forte 			for (i = 0; i < lm->lm_nentries; i++) {
4193fcf3ce44SJohn Forte 				if (lm->lm_plus[i] == NULL)
4194fcf3ce44SJohn Forte 					continue;
4195fcf3ce44SJohn Forte 				ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
4196fcf3ce44SJohn Forte 				if ((ent->ent_lu == lu) &&
4197fcf3ce44SJohn Forte 				    (ent->ent_itl_datap)) {
4198fcf3ce44SJohn Forte 					itl_list[nu++] = ent->ent_itl_datap;
4199fcf3ce44SJohn Forte 					ent->ent_itl_datap = NULL;
4200fcf3ce44SJohn Forte 					if (nu == nmaps) {
4201fcf3ce44SJohn Forte 						rw_exit(&ilport->ilport_lock);
4202fcf3ce44SJohn Forte 						goto dai_scan_done;
4203fcf3ce44SJohn Forte 					}
4204fcf3ce44SJohn Forte 				}
4205fcf3ce44SJohn Forte 			} /* lun table for a session */
4206fcf3ce44SJohn Forte 		} /* sessions */
4207fcf3ce44SJohn Forte 		rw_exit(&ilport->ilport_lock);
4208fcf3ce44SJohn Forte 	} /* ports */
4209fcf3ce44SJohn Forte 
4210fcf3ce44SJohn Forte dai_scan_done:
4211fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
4212fcf3ce44SJohn Forte 
4213fcf3ce44SJohn Forte 	for (i = 0; i < nu; i++) {
4214fcf3ce44SJohn Forte 		stmf_do_itl_dereg(lu, itl_list[i],
4215fcf3ce44SJohn Forte 		    STMF_ITL_REASON_DEREG_REQUEST);
4216fcf3ce44SJohn Forte 	}
4217fcf3ce44SJohn Forte 	kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
4218fcf3ce44SJohn Forte 
4219fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
4220fcf3ce44SJohn Forte }
4221fcf3ce44SJohn Forte 
4222fcf3ce44SJohn Forte stmf_data_buf_t *
stmf_alloc_dbuf(scsi_task_t * task,uint32_t size,uint32_t * pminsize,uint32_t flags)4223fcf3ce44SJohn Forte stmf_alloc_dbuf(scsi_task_t *task, uint32_t size, uint32_t *pminsize,
4224fcf3ce44SJohn Forte     uint32_t flags)
4225fcf3ce44SJohn Forte {
4226fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
4227fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4228fcf3ce44SJohn Forte 	stmf_local_port_t *lport = task->task_lport;
4229fcf3ce44SJohn Forte 	stmf_data_buf_t *dbuf;
4230fcf3ce44SJohn Forte 	uint8_t ndx;
4231fcf3ce44SJohn Forte 
4232fcf3ce44SJohn Forte 	ndx = stmf_first_zero[itask->itask_allocated_buf_map];
4233fcf3ce44SJohn Forte 	if (ndx == 0xff)
4234fcf3ce44SJohn Forte 		return (NULL);
4235fcf3ce44SJohn Forte 	dbuf = itask->itask_dbufs[ndx] = lport->lport_ds->ds_alloc_data_buf(
4236fcf3ce44SJohn Forte 	    task, size, pminsize, flags);
4237fcf3ce44SJohn Forte 	if (dbuf) {
4238fcf3ce44SJohn Forte 		task->task_cur_nbufs++;
4239fcf3ce44SJohn Forte 		itask->itask_allocated_buf_map |= (1 << ndx);
424040c3e8ffSJohn Forte 		dbuf->db_flags &= ~DB_LPORT_XFER_ACTIVE;
4241fcf3ce44SJohn Forte 		dbuf->db_handle = ndx;
4242fcf3ce44SJohn Forte 		return (dbuf);
4243fcf3ce44SJohn Forte 	}
4244fcf3ce44SJohn Forte 
4245fcf3ce44SJohn Forte 	return (NULL);
4246fcf3ce44SJohn Forte }
4247fcf3ce44SJohn Forte 
42483fb517f7SJames Moore stmf_status_t
stmf_setup_dbuf(scsi_task_t * task,stmf_data_buf_t * dbuf,uint32_t flags)42493fb517f7SJames Moore stmf_setup_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t flags)
42503fb517f7SJames Moore {
42513fb517f7SJames Moore 	stmf_i_scsi_task_t *itask =
42523fb517f7SJames Moore 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
42533fb517f7SJames Moore 	stmf_local_port_t *lport = task->task_lport;
42543fb517f7SJames Moore 	uint8_t ndx;
42553fb517f7SJames Moore 	stmf_status_t ret;
42563fb517f7SJames Moore 
42573fb517f7SJames Moore 	ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
42583fb517f7SJames Moore 	ASSERT(lport->lport_ds->ds_setup_dbuf != NULL);
42593fb517f7SJames Moore 	ASSERT(dbuf->db_flags & DB_LU_DATA_BUF);
42603fb517f7SJames Moore 
42613fb517f7SJames Moore 	if ((task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF) == 0)
42623fb517f7SJames Moore 		return (STMF_FAILURE);
42633fb517f7SJames Moore 	if (lport->lport_ds->ds_setup_dbuf == NULL)
42643fb517f7SJames Moore 		return (STMF_FAILURE);
42653fb517f7SJames Moore 
42663fb517f7SJames Moore 	ndx = stmf_first_zero[itask->itask_allocated_buf_map];
42673fb517f7SJames Moore 	if (ndx == 0xff)
42683fb517f7SJames Moore 		return (STMF_FAILURE);
42693fb517f7SJames Moore 	ret = lport->lport_ds->ds_setup_dbuf(task, dbuf, flags);
42703fb517f7SJames Moore 	if (ret == STMF_FAILURE)
42713fb517f7SJames Moore 		return (STMF_FAILURE);
42723fb517f7SJames Moore 	itask->itask_dbufs[ndx] = dbuf;
42733fb517f7SJames Moore 	task->task_cur_nbufs++;
42743fb517f7SJames Moore 	itask->itask_allocated_buf_map |= (1 << ndx);
42753fb517f7SJames Moore 	dbuf->db_handle = ndx;
42763fb517f7SJames Moore 
42773fb517f7SJames Moore 	return (STMF_SUCCESS);
42783fb517f7SJames Moore }
42793fb517f7SJames Moore 
42803fb517f7SJames Moore void
stmf_teardown_dbuf(scsi_task_t * task,stmf_data_buf_t * dbuf)42813fb517f7SJames Moore stmf_teardown_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf)
42823fb517f7SJames Moore {
42833fb517f7SJames Moore 	stmf_i_scsi_task_t *itask =
42843fb517f7SJames Moore 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
42853fb517f7SJames Moore 	stmf_local_port_t *lport = task->task_lport;
42863fb517f7SJames Moore 
42873fb517f7SJames Moore 	ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
42883fb517f7SJames Moore 	ASSERT(lport->lport_ds->ds_teardown_dbuf != NULL);
42893fb517f7SJames Moore 	ASSERT(dbuf->db_flags & DB_LU_DATA_BUF);
42903fb517f7SJames Moore 
42913fb517f7SJames Moore 	itask->itask_allocated_buf_map &= ~(1 << dbuf->db_handle);
42923fb517f7SJames Moore 	task->task_cur_nbufs--;
42933fb517f7SJames Moore 	lport->lport_ds->ds_teardown_dbuf(lport->lport_ds, dbuf);
42943fb517f7SJames Moore }
42953fb517f7SJames Moore 
4296fcf3ce44SJohn Forte void
stmf_free_dbuf(scsi_task_t * task,stmf_data_buf_t * dbuf)4297fcf3ce44SJohn Forte stmf_free_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf)
4298fcf3ce44SJohn Forte {
4299fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
4300fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4301fcf3ce44SJohn Forte 	stmf_local_port_t *lport = task->task_lport;
4302fcf3ce44SJohn Forte 
4303fcf3ce44SJohn Forte 	itask->itask_allocated_buf_map &= ~(1 << dbuf->db_handle);
4304fcf3ce44SJohn Forte 	task->task_cur_nbufs--;
4305fcf3ce44SJohn Forte 	lport->lport_ds->ds_free_data_buf(lport->lport_ds, dbuf);
4306fcf3ce44SJohn Forte }
4307fcf3ce44SJohn Forte 
4308fcf3ce44SJohn Forte stmf_data_buf_t *
stmf_handle_to_buf(scsi_task_t * task,uint8_t h)4309fcf3ce44SJohn Forte stmf_handle_to_buf(scsi_task_t *task, uint8_t h)
4310fcf3ce44SJohn Forte {
4311fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask;
4312fcf3ce44SJohn Forte 
4313fcf3ce44SJohn Forte 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
4314fcf3ce44SJohn Forte 	if (h > 3)
4315fcf3ce44SJohn Forte 		return (NULL);
4316fcf3ce44SJohn Forte 	return (itask->itask_dbufs[h]);
4317fcf3ce44SJohn Forte }
4318fcf3ce44SJohn Forte 
4319fcf3ce44SJohn Forte /* ARGSUSED */
4320fcf3ce44SJohn Forte struct scsi_task *
stmf_task_alloc(struct stmf_local_port * lport,stmf_scsi_session_t * ss,uint8_t * lun,uint16_t cdb_length_in,uint16_t ext_id)4321fcf3ce44SJohn Forte stmf_task_alloc(struct stmf_local_port *lport, stmf_scsi_session_t *ss,
4322fcf3ce44SJohn Forte     uint8_t *lun, uint16_t cdb_length_in, uint16_t ext_id)
4323fcf3ce44SJohn Forte {
4324fcf3ce44SJohn Forte 	stmf_lu_t *lu;
4325fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
4326fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
4327fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask;
4328fcf3ce44SJohn Forte 	stmf_i_scsi_task_t **ppitask;
4329fcf3ce44SJohn Forte 	scsi_task_t *task;
4330fcf3ce44SJohn Forte 	uint8_t	*l;
4331fcf3ce44SJohn Forte 	stmf_lun_map_ent_t *lun_map_ent;
4332fcf3ce44SJohn Forte 	uint16_t cdb_length;
4333fcf3ce44SJohn Forte 	uint16_t luNbr;
4334fcf3ce44SJohn Forte 	uint8_t new_task = 0;
4335fcf3ce44SJohn Forte 
4336fcf3ce44SJohn Forte 	/*
4337fcf3ce44SJohn Forte 	 * We allocate 7 extra bytes for CDB to provide a cdb pointer which
4338fcf3ce44SJohn Forte 	 * is guaranteed to be 8 byte aligned. Some LU providers like OSD
4339fcf3ce44SJohn Forte 	 * depend upon this alignment.
4340fcf3ce44SJohn Forte 	 */
4341fcf3ce44SJohn Forte 	if (cdb_length_in >= 16)
4342fcf3ce44SJohn Forte 		cdb_length = cdb_length_in + 7;
4343fcf3ce44SJohn Forte 	else
4344fcf3ce44SJohn Forte 		cdb_length = 16 + 7;
4345fcf3ce44SJohn Forte 	iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4346fcf3ce44SJohn Forte 	luNbr = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4347fcf3ce44SJohn Forte 	rw_enter(iss->iss_lockp, RW_READER);
4348fcf3ce44SJohn Forte 	lun_map_ent =
4349fcf3ce44SJohn Forte 	    (stmf_lun_map_ent_t *)stmf_get_ent_from_map(iss->iss_sm, luNbr);
4350fcf3ce44SJohn Forte 	if (!lun_map_ent) {
4351fcf3ce44SJohn Forte 		lu = dlun0;
4352fcf3ce44SJohn Forte 	} else {
4353fcf3ce44SJohn Forte 		lu = lun_map_ent->ent_lu;
4354fcf3ce44SJohn Forte 	}
435561dfa509SRick McNeal 
4356fcf3ce44SJohn Forte 	ilu = lu->lu_stmf_private;
4357fcf3ce44SJohn Forte 	if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4358fcf3ce44SJohn Forte 		rw_exit(iss->iss_lockp);
4359fcf3ce44SJohn Forte 		return (NULL);
4360fcf3ce44SJohn Forte 	}
436161dfa509SRick McNeal 
436261dfa509SRick McNeal 	/*
436361dfa509SRick McNeal 	 * if the LUN is being offlined or is offline then only command
436461dfa509SRick McNeal 	 * that are to query the LUN are allowed.  These are handled in
436561dfa509SRick McNeal 	 * stmf via the dlun0 vector.  It is possible that a race condition
436661dfa509SRick McNeal 	 * will cause other commands to arrive while the lun is in the
436761dfa509SRick McNeal 	 * process of being offlined.  Check for those and just let the
436861dfa509SRick McNeal 	 * protocol stack handle the error.
436961dfa509SRick McNeal 	 */
437061dfa509SRick McNeal 	if ((ilu->ilu_state == STMF_STATE_OFFLINING) ||
437161dfa509SRick McNeal 	    (ilu->ilu_state == STMF_STATE_OFFLINE)) {
437261dfa509SRick McNeal 		if (lu != dlun0) {
437361dfa509SRick McNeal 			rw_exit(iss->iss_lockp);
437461dfa509SRick McNeal 			return (NULL);
437561dfa509SRick McNeal 		}
437661dfa509SRick McNeal 	}
437761dfa509SRick McNeal 
4378fcf3ce44SJohn Forte 	do {
4379fcf3ce44SJohn Forte 		if (ilu->ilu_free_tasks == NULL) {
4380fcf3ce44SJohn Forte 			new_task = 1;
4381fcf3ce44SJohn Forte 			break;
4382fcf3ce44SJohn Forte 		}
4383fcf3ce44SJohn Forte 		mutex_enter(&ilu->ilu_task_lock);
4384fcf3ce44SJohn Forte 		for (ppitask = &ilu->ilu_free_tasks; (*ppitask != NULL) &&
4385fcf3ce44SJohn Forte 		    ((*ppitask)->itask_cdb_buf_size < cdb_length);
43865679c89fSjv227347 		    ppitask = &((*ppitask)->itask_lu_free_next))
43875679c89fSjv227347 			;
4388fcf3ce44SJohn Forte 		if (*ppitask) {
4389fcf3ce44SJohn Forte 			itask = *ppitask;
4390fcf3ce44SJohn Forte 			*ppitask = (*ppitask)->itask_lu_free_next;
4391fcf3ce44SJohn Forte 			ilu->ilu_ntasks_free--;
4392fcf3ce44SJohn Forte 			if (ilu->ilu_ntasks_free < ilu->ilu_ntasks_min_free)
4393fcf3ce44SJohn Forte 				ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4394fcf3ce44SJohn Forte 		} else {
4395fcf3ce44SJohn Forte 			new_task = 1;
4396fcf3ce44SJohn Forte 		}
4397fcf3ce44SJohn Forte 		mutex_exit(&ilu->ilu_task_lock);
4398fcf3ce44SJohn Forte 	/* CONSTCOND */
4399fcf3ce44SJohn Forte 	} while (0);
4400fcf3ce44SJohn Forte 
4401fcf3ce44SJohn Forte 	if (!new_task) {
44023fb517f7SJames Moore 		/*
44033fb517f7SJames Moore 		 * Save the task_cdb pointer and zero per cmd fields.
44043fb517f7SJames Moore 		 * We know the task_cdb_length is large enough by task
44053fb517f7SJames Moore 		 * selection process above.
44063fb517f7SJames Moore 		 */
44073fb517f7SJames Moore 		uint8_t *save_cdb;
44083fb517f7SJames Moore 		uintptr_t t_start, t_end;
44093fb517f7SJames Moore 
4410fcf3ce44SJohn Forte 		task = itask->itask_task;
44113fb517f7SJames Moore 		save_cdb = task->task_cdb;	/* save */
44123fb517f7SJames Moore 		t_start = (uintptr_t)&task->task_flags;
44133fb517f7SJames Moore 		t_end = (uintptr_t)&task->task_extended_cmd;
44143fb517f7SJames Moore 		bzero((void *)t_start, (size_t)(t_end - t_start));
44153fb517f7SJames Moore 		task->task_cdb = save_cdb;	/* restore */
4416fcf3ce44SJohn Forte 		itask->itask_ncmds = 0;
4417fcf3ce44SJohn Forte 	} else {
4418fcf3ce44SJohn Forte 		task = (scsi_task_t *)stmf_alloc(STMF_STRUCT_SCSI_TASK,
4419fcf3ce44SJohn Forte 		    cdb_length, AF_FORCE_NOSLEEP);
4420fcf3ce44SJohn Forte 		if (task == NULL) {
4421fcf3ce44SJohn Forte 			rw_exit(iss->iss_lockp);
4422fcf3ce44SJohn Forte 			return (NULL);
4423fcf3ce44SJohn Forte 		}
4424fcf3ce44SJohn Forte 		task->task_lu = lu;
442561dfa509SRick McNeal 		task->task_cdb = (uint8_t *)task->task_port_private;
442661dfa509SRick McNeal 		if ((ulong_t)(task->task_cdb) & 7ul) {
442761dfa509SRick McNeal 			task->task_cdb = (uint8_t *)(((ulong_t)
442861dfa509SRick McNeal 			    (task->task_cdb) + 7ul) & ~(7ul));
442961dfa509SRick McNeal 		}
443061dfa509SRick McNeal 		itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
443161dfa509SRick McNeal 		itask->itask_cdb_buf_size = cdb_length;
443261dfa509SRick McNeal 		mutex_init(&itask->itask_audit_mutex, NULL, MUTEX_DRIVER, NULL);
443361dfa509SRick McNeal 		mutex_init(&itask->itask_mutex, NULL, MUTEX_DRIVER, NULL);
443461dfa509SRick McNeal 	}
443561dfa509SRick McNeal 
443661dfa509SRick McNeal 	/*
443761dfa509SRick McNeal 	 * Since a LUN can be mapped as different LUN ids to different initiator
443861dfa509SRick McNeal 	 * groups, we need to set LUN id for a new task and reset LUN id for
443961dfa509SRick McNeal 	 * a reused task.
444061dfa509SRick McNeal 	 */
4441fcf3ce44SJohn Forte 	l = task->task_lun_no;
4442fcf3ce44SJohn Forte 	l[0] = lun[0];
4443fcf3ce44SJohn Forte 	l[1] = lun[1];
4444fcf3ce44SJohn Forte 	l[2] = lun[2];
4445fcf3ce44SJohn Forte 	l[3] = lun[3];
4446fcf3ce44SJohn Forte 	l[4] = lun[4];
4447fcf3ce44SJohn Forte 	l[5] = lun[5];
4448fcf3ce44SJohn Forte 	l[6] = lun[6];
4449fcf3ce44SJohn Forte 	l[7] = lun[7];
445061dfa509SRick McNeal 
445161dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
4452fcf3ce44SJohn Forte 	task->task_session = ss;
4453fcf3ce44SJohn Forte 	task->task_lport = lport;
4454fcf3ce44SJohn Forte 	task->task_cdb_length = cdb_length_in;
4455fcf3ce44SJohn Forte 	itask->itask_flags = ITASK_IN_TRANSITION;
4456427fcaf8Stim szeto 	itask->itask_waitq_time = 0;
4457427fcaf8Stim szeto 	itask->itask_lu_read_time = itask->itask_lu_write_time = 0;
4458427fcaf8Stim szeto 	itask->itask_lport_read_time = itask->itask_lport_write_time = 0;
4459427fcaf8Stim szeto 	itask->itask_read_xfer = itask->itask_write_xfer = 0;
446040c3e8ffSJohn Forte 	itask->itask_audit_index = 0;
446161dfa509SRick McNeal 	bzero(&itask->itask_audit_records[0],
446261dfa509SRick McNeal 	    sizeof (stmf_task_audit_rec_t) * ITASK_TASK_AUDIT_DEPTH);
446361dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
4464fcf3ce44SJohn Forte 
4465fcf3ce44SJohn Forte 	if (new_task) {
4466fcf3ce44SJohn Forte 		if (lu->lu_task_alloc(task) != STMF_SUCCESS) {
4467fcf3ce44SJohn Forte 			rw_exit(iss->iss_lockp);
4468fcf3ce44SJohn Forte 			stmf_free(task);
4469fcf3ce44SJohn Forte 			return (NULL);
4470fcf3ce44SJohn Forte 		}
4471fcf3ce44SJohn Forte 		mutex_enter(&ilu->ilu_task_lock);
4472fcf3ce44SJohn Forte 		if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4473fcf3ce44SJohn Forte 			mutex_exit(&ilu->ilu_task_lock);
4474fcf3ce44SJohn Forte 			rw_exit(iss->iss_lockp);
4475fcf3ce44SJohn Forte 			stmf_free(task);
4476fcf3ce44SJohn Forte 			return (NULL);
4477fcf3ce44SJohn Forte 		}
4478fcf3ce44SJohn Forte 		itask->itask_lu_next = ilu->ilu_tasks;
4479fcf3ce44SJohn Forte 		if (ilu->ilu_tasks)
4480fcf3ce44SJohn Forte 			ilu->ilu_tasks->itask_lu_prev = itask;
4481fcf3ce44SJohn Forte 		ilu->ilu_tasks = itask;
4482fcf3ce44SJohn Forte 		/* kmem_zalloc automatically makes itask->itask_lu_prev NULL */
4483fcf3ce44SJohn Forte 		ilu->ilu_ntasks++;
4484fcf3ce44SJohn Forte 		mutex_exit(&ilu->ilu_task_lock);
4485fcf3ce44SJohn Forte 	}
4486fcf3ce44SJohn Forte 
4487fcf3ce44SJohn Forte 	itask->itask_ilu_task_cntr = ilu->ilu_cur_task_cntr;
44881a5e258fSJosef 'Jeff' Sipek 	atomic_inc_32(itask->itask_ilu_task_cntr);
4489fcf3ce44SJohn Forte 	itask->itask_start_time = ddi_get_lbolt();
4490fcf3ce44SJohn Forte 
4491fcf3ce44SJohn Forte 	if ((lun_map_ent != NULL) && ((itask->itask_itl_datap =
4492fcf3ce44SJohn Forte 	    lun_map_ent->ent_itl_datap) != NULL)) {
44931a5e258fSJosef 'Jeff' Sipek 		atomic_inc_32(&itask->itask_itl_datap->itl_counter);
4494fcf3ce44SJohn Forte 		task->task_lu_itl_handle = itask->itask_itl_datap->itl_handle;
4495fcf3ce44SJohn Forte 	} else {
4496fcf3ce44SJohn Forte 		itask->itask_itl_datap = NULL;
4497fcf3ce44SJohn Forte 		task->task_lu_itl_handle = NULL;
4498fcf3ce44SJohn Forte 	}
4499fcf3ce44SJohn Forte 
4500fcf3ce44SJohn Forte 	rw_exit(iss->iss_lockp);
4501fcf3ce44SJohn Forte 	return (task);
4502fcf3ce44SJohn Forte }
4503fcf3ce44SJohn Forte 
450461dfa509SRick McNeal /* ARGSUSED */
450545039663SJohn Forte static void
stmf_task_lu_free(scsi_task_t * task,stmf_i_scsi_session_t * iss)450645039663SJohn Forte stmf_task_lu_free(scsi_task_t *task, stmf_i_scsi_session_t *iss)
4507fcf3ce44SJohn Forte {
4508fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
4509fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4510fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
4511fcf3ce44SJohn Forte 
451245039663SJohn Forte 	ASSERT(rw_lock_held(iss->iss_lockp));
451361dfa509SRick McNeal 	ASSERT((itask->itask_flags & ITASK_IN_FREE_LIST) == 0);
451461dfa509SRick McNeal 	ASSERT((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0);
451561dfa509SRick McNeal 	ASSERT((itask->itask_flags & ITASK_IN_TRANSITION) == 0);
451661dfa509SRick McNeal 	ASSERT((itask->itask_flags & ITASK_KNOWN_TO_LU) == 0);
451761dfa509SRick McNeal 	ASSERT(mutex_owned(&itask->itask_mutex));
451861dfa509SRick McNeal 
4519fcf3ce44SJohn Forte 	itask->itask_flags = ITASK_IN_FREE_LIST;
452061dfa509SRick McNeal 	itask->itask_ncmds = 0;
4521437be372SJohn Forte 	itask->itask_proxy_msg_id = 0;
452261dfa509SRick McNeal 	atomic_dec_32(itask->itask_ilu_task_cntr);
452361dfa509SRick McNeal 	itask->itask_worker_next = NULL;
452461dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
452561dfa509SRick McNeal 
4526fcf3ce44SJohn Forte 	mutex_enter(&ilu->ilu_task_lock);
4527fcf3ce44SJohn Forte 	itask->itask_lu_free_next = ilu->ilu_free_tasks;
4528fcf3ce44SJohn Forte 	ilu->ilu_free_tasks = itask;
4529fcf3ce44SJohn Forte 	ilu->ilu_ntasks_free++;
4530a49dc893SSaso Kiselkov 	if (ilu->ilu_ntasks == ilu->ilu_ntasks_free)
4531a49dc893SSaso Kiselkov 		cv_signal(&ilu->ilu_offline_pending_cv);
4532fcf3ce44SJohn Forte 	mutex_exit(&ilu->ilu_task_lock);
4533fcf3ce44SJohn Forte }
4534fcf3ce44SJohn Forte 
4535fcf3ce44SJohn Forte void
stmf_task_lu_check_freelist(stmf_i_lu_t * ilu)4536fcf3ce44SJohn Forte stmf_task_lu_check_freelist(stmf_i_lu_t *ilu)
4537fcf3ce44SJohn Forte {
4538fcf3ce44SJohn Forte 	uint32_t	num_to_release, ndx;
4539fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask;
4540fcf3ce44SJohn Forte 	stmf_lu_t	*lu = ilu->ilu_lu;
4541fcf3ce44SJohn Forte 
4542fcf3ce44SJohn Forte 	ASSERT(ilu->ilu_ntasks_min_free <= ilu->ilu_ntasks_free);
4543fcf3ce44SJohn Forte 
4544fcf3ce44SJohn Forte 	/* free half of the minimal free of the free tasks */
4545fcf3ce44SJohn Forte 	num_to_release = (ilu->ilu_ntasks_min_free + 1) / 2;
4546fcf3ce44SJohn Forte 	if (!num_to_release) {
4547fcf3ce44SJohn Forte 		return;
4548fcf3ce44SJohn Forte 	}
4549fcf3ce44SJohn Forte 	for (ndx = 0; ndx < num_to_release; ndx++) {
4550fcf3ce44SJohn Forte 		mutex_enter(&ilu->ilu_task_lock);
4551fcf3ce44SJohn Forte 		itask = ilu->ilu_free_tasks;
4552fcf3ce44SJohn Forte 		if (itask == NULL) {
4553fcf3ce44SJohn Forte 			mutex_exit(&ilu->ilu_task_lock);
4554fcf3ce44SJohn Forte 			break;
4555fcf3ce44SJohn Forte 		}
4556fcf3ce44SJohn Forte 		ilu->ilu_free_tasks = itask->itask_lu_free_next;
4557fcf3ce44SJohn Forte 		ilu->ilu_ntasks_free--;
4558fcf3ce44SJohn Forte 		mutex_exit(&ilu->ilu_task_lock);
4559fcf3ce44SJohn Forte 
4560fcf3ce44SJohn Forte 		lu->lu_task_free(itask->itask_task);
4561fcf3ce44SJohn Forte 		mutex_enter(&ilu->ilu_task_lock);
4562fcf3ce44SJohn Forte 		if (itask->itask_lu_next)
4563fcf3ce44SJohn Forte 			itask->itask_lu_next->itask_lu_prev =
4564fcf3ce44SJohn Forte 			    itask->itask_lu_prev;
4565fcf3ce44SJohn Forte 		if (itask->itask_lu_prev)
4566fcf3ce44SJohn Forte 			itask->itask_lu_prev->itask_lu_next =
4567fcf3ce44SJohn Forte 			    itask->itask_lu_next;
4568fcf3ce44SJohn Forte 		else
4569fcf3ce44SJohn Forte 			ilu->ilu_tasks = itask->itask_lu_next;
4570fcf3ce44SJohn Forte 
4571fcf3ce44SJohn Forte 		ilu->ilu_ntasks--;
4572fcf3ce44SJohn Forte 		mutex_exit(&ilu->ilu_task_lock);
4573fcf3ce44SJohn Forte 		stmf_free(itask->itask_task);
4574fcf3ce44SJohn Forte 	}
4575fcf3ce44SJohn Forte }
4576fcf3ce44SJohn Forte 
4577fcf3ce44SJohn Forte /*
4578fcf3ce44SJohn Forte  * Called with stmf_lock held
4579fcf3ce44SJohn Forte  */
4580fcf3ce44SJohn Forte void
stmf_check_freetask()4581fcf3ce44SJohn Forte stmf_check_freetask()
4582fcf3ce44SJohn Forte {
4583fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
4584fcf3ce44SJohn Forte 	clock_t	endtime = ddi_get_lbolt() + drv_usectohz(10000);
4585fcf3ce44SJohn Forte 
4586fcf3ce44SJohn Forte 	/* stmf_svc_ilu_draining may get changed after stmf_lock is released */
4587fcf3ce44SJohn Forte 	while ((ilu = stmf_state.stmf_svc_ilu_draining) != NULL) {
4588fcf3ce44SJohn Forte 		stmf_state.stmf_svc_ilu_draining = ilu->ilu_next;
4589fcf3ce44SJohn Forte 		if (!ilu->ilu_ntasks_min_free) {
4590fcf3ce44SJohn Forte 			ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4591fcf3ce44SJohn Forte 			continue;
4592fcf3ce44SJohn Forte 		}
4593fcf3ce44SJohn Forte 		ilu->ilu_flags |= ILU_STALL_DEREGISTER;
4594fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
4595fcf3ce44SJohn Forte 		stmf_task_lu_check_freelist(ilu);
4596fcf3ce44SJohn Forte 		/*
4597fcf3ce44SJohn Forte 		 * we do not care about the accuracy of
4598fcf3ce44SJohn Forte 		 * ilu_ntasks_min_free, so we don't lock here
4599fcf3ce44SJohn Forte 		 */
4600fcf3ce44SJohn Forte 		ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4601fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
4602fcf3ce44SJohn Forte 		ilu->ilu_flags &= ~ILU_STALL_DEREGISTER;
4603fcf3ce44SJohn Forte 		cv_broadcast(&stmf_state.stmf_cv);
4604fcf3ce44SJohn Forte 		if (ddi_get_lbolt() >= endtime)
4605fcf3ce44SJohn Forte 			break;
4606fcf3ce44SJohn Forte 	}
4607fcf3ce44SJohn Forte }
4608fcf3ce44SJohn Forte 
460961dfa509SRick McNeal /*
461061dfa509SRick McNeal  * Since this method is looking to find tasks that are stuck, lost, or senile
461161dfa509SRick McNeal  * it should be more willing to give up scaning during this time period. This
461261dfa509SRick McNeal  * is why mutex_tryenter is now used instead of the standard mutex_enter.
461361dfa509SRick McNeal  * There has been at least one case were the following occurred.
461461dfa509SRick McNeal  *
461561dfa509SRick McNeal  * 1) The iscsit_deferred() method is trying to register a session and
461661dfa509SRick McNeal  *    needs the global lock which is held.
461761dfa509SRick McNeal  * 2) Another thread which holds the global lock is trying to deregister a
461861dfa509SRick McNeal  *    session and needs the session lock.
461961dfa509SRick McNeal  * 3) A third thread is allocating a stmf task that has grabbed the session
462061dfa509SRick McNeal  *    lock and is trying to grab the lun task lock.
462161dfa509SRick McNeal  * 4) There's a timeout thread that has the lun task lock and is trying to grab
462261dfa509SRick McNeal  *    a specific task lock.
462361dfa509SRick McNeal  * 5) The thread that has the task lock is waiting for the ref count to go to
462461dfa509SRick McNeal  *    zero.
462561dfa509SRick McNeal  * 6) There's a task that would drop the count to zero, but it's in the task
462661dfa509SRick McNeal  *    queue waiting to run and is stuck because of #1 is currently block.
462761dfa509SRick McNeal  *
462861dfa509SRick McNeal  * This method is number 4 in the above chain of events. Had this code
462961dfa509SRick McNeal  * originally used mutex_tryenter the chain would have been broken and the
463061dfa509SRick McNeal  * system wouldn't have hung. So, now this method uses mutex_tryenter and
463161dfa509SRick McNeal  * you know why it does so.
463261dfa509SRick McNeal  */
463361dfa509SRick McNeal /* ---- Only one thread calls stmf_do_ilu_timeouts so no lock required ---- */
463461dfa509SRick McNeal typedef struct stmf_bailout_cnt {
463561dfa509SRick McNeal 	int	no_ilu_lock;
463661dfa509SRick McNeal 	int	no_task_lock;
463761dfa509SRick McNeal 	int	tasks_checked;
463861dfa509SRick McNeal } stmf_bailout_cnt_t;
463961dfa509SRick McNeal 
464061dfa509SRick McNeal stmf_bailout_cnt_t stmf_bailout;
464161dfa509SRick McNeal 
464261dfa509SRick McNeal static void
stmf_do_ilu_timeouts(stmf_i_lu_t * ilu)4643fcf3ce44SJohn Forte stmf_do_ilu_timeouts(stmf_i_lu_t *ilu)
4644fcf3ce44SJohn Forte {
4645fcf3ce44SJohn Forte 	clock_t l = ddi_get_lbolt();
4646fcf3ce44SJohn Forte 	clock_t ps = drv_usectohz(1000000);
4647fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask;
4648fcf3ce44SJohn Forte 	scsi_task_t *task;
4649fcf3ce44SJohn Forte 	uint32_t to;
4650fcf3ce44SJohn Forte 
465161dfa509SRick McNeal 	if (mutex_tryenter(&ilu->ilu_task_lock) == 0) {
465261dfa509SRick McNeal 		stmf_bailout.no_ilu_lock++;
465361dfa509SRick McNeal 		return;
465461dfa509SRick McNeal 	}
465561dfa509SRick McNeal 
4656fcf3ce44SJohn Forte 	for (itask = ilu->ilu_tasks; itask != NULL;
4657fcf3ce44SJohn Forte 	    itask = itask->itask_lu_next) {
465861dfa509SRick McNeal 		if (mutex_tryenter(&itask->itask_mutex) == 0) {
465961dfa509SRick McNeal 			stmf_bailout.no_task_lock++;
466061dfa509SRick McNeal 			continue;
466161dfa509SRick McNeal 		}
466261dfa509SRick McNeal 		stmf_bailout.tasks_checked++;
4663fcf3ce44SJohn Forte 		if (itask->itask_flags & (ITASK_IN_FREE_LIST |
4664fcf3ce44SJohn Forte 		    ITASK_BEING_ABORTED)) {
466561dfa509SRick McNeal 			mutex_exit(&itask->itask_mutex);
4666fcf3ce44SJohn Forte 			continue;
4667fcf3ce44SJohn Forte 		}
4668fcf3ce44SJohn Forte 		task = itask->itask_task;
4669fcf3ce44SJohn Forte 		if (task->task_timeout == 0)
4670fcf3ce44SJohn Forte 			to = stmf_default_task_timeout;
4671fcf3ce44SJohn Forte 		else
4672fcf3ce44SJohn Forte 			to = task->task_timeout;
467361dfa509SRick McNeal 
467461dfa509SRick McNeal 		if ((itask->itask_start_time + (to * ps)) > l) {
467561dfa509SRick McNeal 			mutex_exit(&itask->itask_mutex);
4676fcf3ce44SJohn Forte 			continue;
467761dfa509SRick McNeal 		}
467861dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
4679fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
4680fcf3ce44SJohn Forte 		    STMF_TIMEOUT, NULL);
4681fcf3ce44SJohn Forte 	}
4682fcf3ce44SJohn Forte 	mutex_exit(&ilu->ilu_task_lock);
4683fcf3ce44SJohn Forte }
4684fcf3ce44SJohn Forte 
4685fcf3ce44SJohn Forte /*
4686fcf3ce44SJohn Forte  * Called with stmf_lock held
4687fcf3ce44SJohn Forte  */
4688fcf3ce44SJohn Forte void
stmf_check_ilu_timing()4689fcf3ce44SJohn Forte stmf_check_ilu_timing()
4690fcf3ce44SJohn Forte {
4691fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
4692fcf3ce44SJohn Forte 	clock_t	endtime = ddi_get_lbolt() + drv_usectohz(10000);
4693fcf3ce44SJohn Forte 
4694fcf3ce44SJohn Forte 	/* stmf_svc_ilu_timing may get changed after stmf_lock is released */
4695fcf3ce44SJohn Forte 	while ((ilu = stmf_state.stmf_svc_ilu_timing) != NULL) {
4696fcf3ce44SJohn Forte 		stmf_state.stmf_svc_ilu_timing = ilu->ilu_next;
4697fcf3ce44SJohn Forte 		if (ilu->ilu_cur_task_cntr == (&ilu->ilu_task_cntr1)) {
4698fcf3ce44SJohn Forte 			if (ilu->ilu_task_cntr2 == 0) {
4699fcf3ce44SJohn Forte 				ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr2;
4700fcf3ce44SJohn Forte 				continue;
4701fcf3ce44SJohn Forte 			}
4702fcf3ce44SJohn Forte 		} else {
4703fcf3ce44SJohn Forte 			if (ilu->ilu_task_cntr1 == 0) {
4704fcf3ce44SJohn Forte 				ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
4705fcf3ce44SJohn Forte 				continue;
4706fcf3ce44SJohn Forte 			}
4707fcf3ce44SJohn Forte 		}
4708fcf3ce44SJohn Forte 		/*
4709fcf3ce44SJohn Forte 		 * If we are here then it means that there is some slowdown
4710fcf3ce44SJohn Forte 		 * in tasks on this lu. We need to check.
4711fcf3ce44SJohn Forte 		 */
4712fcf3ce44SJohn Forte 		ilu->ilu_flags |= ILU_STALL_DEREGISTER;
4713fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
4714fcf3ce44SJohn Forte 		stmf_do_ilu_timeouts(ilu);
4715fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
4716fcf3ce44SJohn Forte 		ilu->ilu_flags &= ~ILU_STALL_DEREGISTER;
4717fcf3ce44SJohn Forte 		cv_broadcast(&stmf_state.stmf_cv);
4718fcf3ce44SJohn Forte 		if (ddi_get_lbolt() >= endtime)
4719fcf3ce44SJohn Forte 			break;
4720fcf3ce44SJohn Forte 	}
4721fcf3ce44SJohn Forte }
4722fcf3ce44SJohn Forte 
4723fcf3ce44SJohn Forte /*
4724fcf3ce44SJohn Forte  * Kills all tasks on a lu except tm_task
4725fcf3ce44SJohn Forte  */
4726fcf3ce44SJohn Forte void
stmf_task_lu_killall(stmf_lu_t * lu,scsi_task_t * tm_task,stmf_status_t s)4727fcf3ce44SJohn Forte stmf_task_lu_killall(stmf_lu_t *lu, scsi_task_t *tm_task, stmf_status_t s)
4728fcf3ce44SJohn Forte {
4729fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4730fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask;
4731fcf3ce44SJohn Forte 
4732fcf3ce44SJohn Forte 	mutex_enter(&ilu->ilu_task_lock);
4733fcf3ce44SJohn Forte 	for (itask = ilu->ilu_tasks; itask != NULL;
4734fcf3ce44SJohn Forte 	    itask = itask->itask_lu_next) {
473561dfa509SRick McNeal 		mutex_enter(&itask->itask_mutex);
473661dfa509SRick McNeal 		if (itask->itask_flags & ITASK_IN_FREE_LIST) {
473761dfa509SRick McNeal 			mutex_exit(&itask->itask_mutex);
4738fcf3ce44SJohn Forte 			continue;
473961dfa509SRick McNeal 		}
474061dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
4741fcf3ce44SJohn Forte 		if (itask->itask_task == tm_task)
4742fcf3ce44SJohn Forte 			continue;
4743fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, itask->itask_task, s, NULL);
4744fcf3ce44SJohn Forte 	}
4745fcf3ce44SJohn Forte 	mutex_exit(&ilu->ilu_task_lock);
4746fcf3ce44SJohn Forte }
4747fcf3ce44SJohn Forte 
4748fcf3ce44SJohn Forte void
stmf_free_task_bufs(stmf_i_scsi_task_t * itask,stmf_local_port_t * lport)4749fcf3ce44SJohn Forte stmf_free_task_bufs(stmf_i_scsi_task_t *itask, stmf_local_port_t *lport)
4750fcf3ce44SJohn Forte {
4751fcf3ce44SJohn Forte 	int i;
4752fcf3ce44SJohn Forte 	uint8_t map;
4753fcf3ce44SJohn Forte 
47543fb517f7SJames Moore 	if ((map = itask->itask_allocated_buf_map) == 0)
47553fb517f7SJames Moore 		return;
4756fcf3ce44SJohn Forte 	for (i = 0; i < 4; i++) {
4757fcf3ce44SJohn Forte 		if (map & 1) {
4758fcf3ce44SJohn Forte 			stmf_data_buf_t *dbuf;
4759fcf3ce44SJohn Forte 
4760fcf3ce44SJohn Forte 			dbuf = itask->itask_dbufs[i];
47613fb517f7SJames Moore 			if (dbuf->db_xfer_start_timestamp) {
4762427fcaf8Stim szeto 				stmf_lport_xfer_done(itask, dbuf);
4763427fcaf8Stim szeto 			}
47643fb517f7SJames Moore 			if (dbuf->db_flags & DB_LU_DATA_BUF) {
47653fb517f7SJames Moore 				/*
47663fb517f7SJames Moore 				 * LU needs to clean up buffer.
47673fb517f7SJames Moore 				 * LU is required to free the buffer
47683fb517f7SJames Moore 				 * in the xfer_done handler.
47693fb517f7SJames Moore 				 */
47703fb517f7SJames Moore 				scsi_task_t *task = itask->itask_task;
47713fb517f7SJames Moore 				stmf_lu_t *lu = task->task_lu;
47723fb517f7SJames Moore 
47733fb517f7SJames Moore 				lu->lu_dbuf_free(task, dbuf);
47743fb517f7SJames Moore 				ASSERT(((itask->itask_allocated_buf_map>>i)
47753fb517f7SJames Moore 				    & 1) == 0); /* must be gone */
47763fb517f7SJames Moore 			} else {
47773fb517f7SJames Moore 				ASSERT(dbuf->db_lu_private == NULL);
47783fb517f7SJames Moore 				dbuf->db_lu_private = NULL;
4779fcf3ce44SJohn Forte 				lport->lport_ds->ds_free_data_buf(
4780fcf3ce44SJohn Forte 				    lport->lport_ds, dbuf);
4781fcf3ce44SJohn Forte 			}
47823fb517f7SJames Moore 		}
4783fcf3ce44SJohn Forte 		map >>= 1;
4784fcf3ce44SJohn Forte 	}
4785fcf3ce44SJohn Forte 	itask->itask_allocated_buf_map = 0;
4786fcf3ce44SJohn Forte }
4787fcf3ce44SJohn Forte 
4788fcf3ce44SJohn Forte void
stmf_task_free(scsi_task_t * task)4789fcf3ce44SJohn Forte stmf_task_free(scsi_task_t *task)
4790fcf3ce44SJohn Forte {
4791fcf3ce44SJohn Forte 	stmf_local_port_t *lport = task->task_lport;
4792fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
4793fcf3ce44SJohn Forte 	    task->task_stmf_private;
479445039663SJohn Forte 	stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
479545039663SJohn Forte 	    task->task_session->ss_stmf_private;
479661dfa509SRick McNeal 	stmf_lu_t *lu = task->task_lu;
4797fcf3ce44SJohn Forte 
479840c3e8ffSJohn Forte 	stmf_task_audit(itask, TE_TASK_FREE, CMD_OR_IOF_NA, NULL);
479961dfa509SRick McNeal 	ASSERT(mutex_owned(&itask->itask_mutex));
480061dfa509SRick McNeal 	if ((lu != NULL) && (lu->lu_task_done != NULL))
480161dfa509SRick McNeal 		lu->lu_task_done(task);
4802fcf3ce44SJohn Forte 	stmf_free_task_bufs(itask, lport);
4803427fcaf8Stim szeto 	stmf_itl_task_done(itask);
4804427fcaf8Stim szeto 	DTRACE_PROBE2(stmf__task__end, scsi_task_t *, task,
4805427fcaf8Stim szeto 	    hrtime_t,
4806427fcaf8Stim szeto 	    itask->itask_done_timestamp - itask->itask_start_timestamp);
4807fcf3ce44SJohn Forte 	if (itask->itask_itl_datap) {
48081a5e258fSJosef 'Jeff' Sipek 		if (atomic_dec_32_nv(&itask->itask_itl_datap->itl_counter) ==
48091a5e258fSJosef 'Jeff' Sipek 		    0) {
4810fcf3ce44SJohn Forte 			stmf_release_itl_handle(task->task_lu,
4811fcf3ce44SJohn Forte 			    itask->itask_itl_datap);
4812fcf3ce44SJohn Forte 		}
4813fcf3ce44SJohn Forte 	}
481445039663SJohn Forte 
481561dfa509SRick McNeal 	/*
481661dfa509SRick McNeal 	 * To prevent a deadlock condition must release the itask_mutex,
481761dfa509SRick McNeal 	 * grab a reader lock on iss_lockp and then reacquire the itask_mutex.
481861dfa509SRick McNeal 	 */
481961dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
482045039663SJohn Forte 	rw_enter(iss->iss_lockp, RW_READER);
482161dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
482261dfa509SRick McNeal 
4823fcf3ce44SJohn Forte 	lport->lport_task_free(task);
4824fcf3ce44SJohn Forte 	if (itask->itask_worker) {
48251a5e258fSJosef 'Jeff' Sipek 		atomic_dec_32(&stmf_cur_ntasks);
48261a5e258fSJosef 'Jeff' Sipek 		atomic_dec_32(&itask->itask_worker->worker_ref_count);
4827fcf3ce44SJohn Forte 	}
4828fcf3ce44SJohn Forte 	/*
4829fcf3ce44SJohn Forte 	 * After calling stmf_task_lu_free, the task pointer can no longer
4830fcf3ce44SJohn Forte 	 * be trusted.
4831fcf3ce44SJohn Forte 	 */
483245039663SJohn Forte 	stmf_task_lu_free(task, iss);
483345039663SJohn Forte 	rw_exit(iss->iss_lockp);
4834fcf3ce44SJohn Forte }
4835fcf3ce44SJohn Forte 
4836fcf3ce44SJohn Forte void
stmf_post_task(scsi_task_t * task,stmf_data_buf_t * dbuf)4837fcf3ce44SJohn Forte stmf_post_task(scsi_task_t *task, stmf_data_buf_t *dbuf)
4838fcf3ce44SJohn Forte {
4839fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
4840fcf3ce44SJohn Forte 	    task->task_stmf_private;
4841fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
4842fcf3ce44SJohn Forte 	int nv;
484361dfa509SRick McNeal 	uint32_t new;
4844fcf3ce44SJohn Forte 	uint32_t ct;
484561dfa509SRick McNeal 	stmf_worker_t *w;
4846fcf3ce44SJohn Forte 	uint8_t tm;
4847fcf3ce44SJohn Forte 
4848fcf3ce44SJohn Forte 	if (task->task_max_nbufs > 4)
4849fcf3ce44SJohn Forte 		task->task_max_nbufs = 4;
4850fcf3ce44SJohn Forte 	task->task_cur_nbufs = 0;
4851fcf3ce44SJohn Forte 	/* Latest value of currently running tasks */
48521a5e258fSJosef 'Jeff' Sipek 	ct = atomic_inc_32_nv(&stmf_cur_ntasks);
4853fcf3ce44SJohn Forte 
4854fcf3ce44SJohn Forte 	/* Select the next worker using round robin */
485561dfa509SRick McNeal 	mutex_enter(&stmf_worker_sel_mx);
485661dfa509SRick McNeal 	stmf_worker_sel_counter++;
485761dfa509SRick McNeal 	if (stmf_worker_sel_counter >= stmf_nworkers)
485861dfa509SRick McNeal 		stmf_worker_sel_counter = 0;
485961dfa509SRick McNeal 	nv = stmf_worker_sel_counter;
486061dfa509SRick McNeal 
486161dfa509SRick McNeal 	/* if the selected worker is not idle then bump to the next worker */
486261dfa509SRick McNeal 	if (stmf_workers[nv].worker_queue_depth > 0) {
486361dfa509SRick McNeal 		stmf_worker_sel_counter++;
486461dfa509SRick McNeal 		if (stmf_worker_sel_counter >= stmf_nworkers)
486561dfa509SRick McNeal 			stmf_worker_sel_counter = 0;
486661dfa509SRick McNeal 		nv = stmf_worker_sel_counter;
4867fcf3ce44SJohn Forte 	}
486861dfa509SRick McNeal 	mutex_exit(&stmf_worker_sel_mx);
486961dfa509SRick McNeal 
4870fcf3ce44SJohn Forte 	w = &stmf_workers[nv];
4871fcf3ce44SJohn Forte 
487261dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
487361dfa509SRick McNeal 	mutex_enter(&w->worker_lock);
4874034d83c4Stim szeto 
4875fcf3ce44SJohn Forte 	itask->itask_worker = w;
487661dfa509SRick McNeal 
4877fcf3ce44SJohn Forte 	/*
4878fcf3ce44SJohn Forte 	 * Track max system load inside the worker as we already have the
4879fcf3ce44SJohn Forte 	 * worker lock (no point implementing another lock). The service
4880fcf3ce44SJohn Forte 	 * thread will do the comparisons and figure out the max overall
4881fcf3ce44SJohn Forte 	 * system load.
4882fcf3ce44SJohn Forte 	 */
4883fcf3ce44SJohn Forte 	if (w->worker_max_sys_qdepth_pu < ct)
4884fcf3ce44SJohn Forte 		w->worker_max_sys_qdepth_pu = ct;
4885fcf3ce44SJohn Forte 
488661dfa509SRick McNeal 	new = itask->itask_flags;
488761dfa509SRick McNeal 	new |= ITASK_KNOWN_TO_TGT_PORT;
4888fcf3ce44SJohn Forte 	if (task->task_mgmt_function) {
4889fcf3ce44SJohn Forte 		tm = task->task_mgmt_function;
4890fcf3ce44SJohn Forte 		if ((tm == TM_TARGET_RESET) ||
4891fcf3ce44SJohn Forte 		    (tm == TM_TARGET_COLD_RESET) ||
4892fcf3ce44SJohn Forte 		    (tm == TM_TARGET_WARM_RESET)) {
4893fcf3ce44SJohn Forte 			new |= ITASK_DEFAULT_HANDLING;
4894fcf3ce44SJohn Forte 		}
4895fcf3ce44SJohn Forte 	} else if (task->task_cdb[0] == SCMD_REPORT_LUNS) {
4896fcf3ce44SJohn Forte 		new |= ITASK_DEFAULT_HANDLING;
4897fcf3ce44SJohn Forte 	}
4898fcf3ce44SJohn Forte 	new &= ~ITASK_IN_TRANSITION;
489961dfa509SRick McNeal 	itask->itask_flags = new;
4900427fcaf8Stim szeto 
4901427fcaf8Stim szeto 	stmf_itl_task_start(itask);
4902427fcaf8Stim szeto 
4903fcf3ce44SJohn Forte 	itask->itask_cmd_stack[0] = ITASK_CMD_NEW_TASK;
4904fcf3ce44SJohn Forte 	itask->itask_ncmds = 1;
490561dfa509SRick McNeal 
490661dfa509SRick McNeal 	if ((task->task_flags & TF_INITIAL_BURST) &&
490761dfa509SRick McNeal 	    !(curthread->t_flag & T_INTR_THREAD)) {
490861dfa509SRick McNeal 		stmf_update_kstat_lu_io(task, dbuf);
490961dfa509SRick McNeal 		stmf_update_kstat_lport_io(task, dbuf);
491061dfa509SRick McNeal 		stmf_update_kstat_rport_io(task, dbuf);
491161dfa509SRick McNeal 	}
491261dfa509SRick McNeal 
491340c3e8ffSJohn Forte 	stmf_task_audit(itask, TE_TASK_START, CMD_OR_IOF_NA, dbuf);
4914fcf3ce44SJohn Forte 	if (dbuf) {
4915fcf3ce44SJohn Forte 		itask->itask_allocated_buf_map = 1;
4916fcf3ce44SJohn Forte 		itask->itask_dbufs[0] = dbuf;
4917fcf3ce44SJohn Forte 		dbuf->db_handle = 0;
4918fcf3ce44SJohn Forte 	} else {
4919fcf3ce44SJohn Forte 		itask->itask_allocated_buf_map = 0;
4920fcf3ce44SJohn Forte 		itask->itask_dbufs[0] = NULL;
4921fcf3ce44SJohn Forte 	}
4922034d83c4Stim szeto 
492361dfa509SRick McNeal 	STMF_ENQUEUE_ITASK(w, itask);
492461dfa509SRick McNeal 
4925fcf3ce44SJohn Forte 	mutex_exit(&w->worker_lock);
492661dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
4927fcf3ce44SJohn Forte 
4928fcf3ce44SJohn Forte 	/*
4929fcf3ce44SJohn Forte 	 * This can only happen if during stmf_task_alloc(), ILU_RESET_ACTIVE
4930fcf3ce44SJohn Forte 	 * was set between checking of ILU_RESET_ACTIVE and clearing of the
4931fcf3ce44SJohn Forte 	 * ITASK_IN_FREE_LIST flag. Take care of these "sneaked-in" tasks here.
4932fcf3ce44SJohn Forte 	 */
4933fcf3ce44SJohn Forte 	if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4934fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ABORTED, NULL);
4935fcf3ce44SJohn Forte 	}
4936fcf3ce44SJohn Forte }
4937fcf3ce44SJohn Forte 
493840c3e8ffSJohn Forte static void
stmf_task_audit(stmf_i_scsi_task_t * itask,task_audit_event_t te,uint32_t cmd_or_iof,stmf_data_buf_t * dbuf)493940c3e8ffSJohn Forte stmf_task_audit(stmf_i_scsi_task_t *itask,
494040c3e8ffSJohn Forte     task_audit_event_t te, uint32_t cmd_or_iof, stmf_data_buf_t *dbuf)
494140c3e8ffSJohn Forte {
494240c3e8ffSJohn Forte 	stmf_task_audit_rec_t *ar;
494340c3e8ffSJohn Forte 
494440c3e8ffSJohn Forte 	mutex_enter(&itask->itask_audit_mutex);
494540c3e8ffSJohn Forte 	ar = &itask->itask_audit_records[itask->itask_audit_index++];
494640c3e8ffSJohn Forte 	itask->itask_audit_index &= (ITASK_TASK_AUDIT_DEPTH - 1);
494740c3e8ffSJohn Forte 	ar->ta_event = te;
494840c3e8ffSJohn Forte 	ar->ta_cmd_or_iof = cmd_or_iof;
494940c3e8ffSJohn Forte 	ar->ta_itask_flags = itask->itask_flags;
495040c3e8ffSJohn Forte 	ar->ta_dbuf = dbuf;
495140c3e8ffSJohn Forte 	gethrestime(&ar->ta_timestamp);
495240c3e8ffSJohn Forte 	mutex_exit(&itask->itask_audit_mutex);
495340c3e8ffSJohn Forte }
495440c3e8ffSJohn Forte 
495540c3e8ffSJohn Forte 
4956fcf3ce44SJohn Forte /*
4957fcf3ce44SJohn Forte  * ++++++++++++++ ABORT LOGIC ++++++++++++++++++++
4958fcf3ce44SJohn Forte  * Once ITASK_BEING_ABORTED is set, ITASK_KNOWN_TO_LU can be reset already
4959fcf3ce44SJohn Forte  * i.e. before ITASK_BEING_ABORTED being set. But if it was not, it cannot
4960fcf3ce44SJohn Forte  * be reset until the LU explicitly calls stmf_task_lu_aborted(). Of course
4961fcf3ce44SJohn Forte  * the LU will make this call only if we call the LU's abort entry point.
4962fcf3ce44SJohn Forte  * we will only call that entry point if ITASK_KNOWN_TO_LU was set.
4963fcf3ce44SJohn Forte  *
4964fcf3ce44SJohn Forte  * Same logic applies for the port.
4965fcf3ce44SJohn Forte  *
4966fcf3ce44SJohn Forte  * Also ITASK_BEING_ABORTED will not be allowed to set if both KNOWN_TO_LU
4967fcf3ce44SJohn Forte  * and KNOWN_TO_TGT_PORT are reset.
4968fcf3ce44SJohn Forte  *
4969fcf3ce44SJohn Forte  * +++++++++++++++++++++++++++++++++++++++++++++++
4970fcf3ce44SJohn Forte  */
4971fcf3ce44SJohn Forte 
4972fcf3ce44SJohn Forte stmf_status_t
stmf_xfer_data(scsi_task_t * task,stmf_data_buf_t * dbuf,uint32_t ioflags)4973fcf3ce44SJohn Forte stmf_xfer_data(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t ioflags)
4974fcf3ce44SJohn Forte {
497540c3e8ffSJohn Forte 	stmf_status_t ret = STMF_SUCCESS;
4976e17f3b22Stim szeto 
4977fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
4978fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
4979fcf3ce44SJohn Forte 
498040c3e8ffSJohn Forte 	stmf_task_audit(itask, TE_XFER_START, ioflags, dbuf);
498140c3e8ffSJohn Forte 
498261dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
4983fcf3ce44SJohn Forte 	if (ioflags & STMF_IOF_LU_DONE) {
498461dfa509SRick McNeal 		if (itask->itask_flags & ITASK_BEING_ABORTED) {
498561dfa509SRick McNeal 			mutex_exit(&itask->itask_mutex);
4986fcf3ce44SJohn Forte 			return (STMF_ABORTED);
4987fcf3ce44SJohn Forte 		}
498861dfa509SRick McNeal 		itask->itask_flags &= ~ITASK_KNOWN_TO_LU;
498961dfa509SRick McNeal 	}
499061dfa509SRick McNeal 	if ((itask->itask_flags & ITASK_BEING_ABORTED) != 0) {
499161dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
4992fcf3ce44SJohn Forte 		return (STMF_ABORTED);
499361dfa509SRick McNeal 	}
499461dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
499561dfa509SRick McNeal 
4996fcf3ce44SJohn Forte #ifdef	DEBUG
4997427fcaf8Stim szeto 	if (!(ioflags & STMF_IOF_STATS_ONLY) && stmf_drop_buf_counter > 0) {
499861dfa509SRick McNeal 		if (atomic_dec_32_nv((uint32_t *)&stmf_drop_buf_counter) == 1)
4999fcf3ce44SJohn Forte 			return (STMF_SUCCESS);
5000fcf3ce44SJohn Forte 	}
5001fcf3ce44SJohn Forte #endif
5002034d83c4Stim szeto 
5003034d83c4Stim szeto 	stmf_update_kstat_lu_io(task, dbuf);
5004034d83c4Stim szeto 	stmf_update_kstat_lport_io(task, dbuf);
500561dfa509SRick McNeal 	stmf_update_kstat_rport_io(task, dbuf);
5006427fcaf8Stim szeto 	stmf_lport_xfer_start(itask, dbuf);
5007427fcaf8Stim szeto 	if (ioflags & STMF_IOF_STATS_ONLY) {
5008427fcaf8Stim szeto 		stmf_lport_xfer_done(itask, dbuf);
5009427fcaf8Stim szeto 		return (STMF_SUCCESS);
5010427fcaf8Stim szeto 	}
5011034d83c4Stim szeto 
501240c3e8ffSJohn Forte 	dbuf->db_flags |= DB_LPORT_XFER_ACTIVE;
5013e17f3b22Stim szeto 	ret = task->task_lport->lport_xfer_data(task, dbuf, ioflags);
5014427fcaf8Stim szeto 
5015427fcaf8Stim szeto 	/*
5016427fcaf8Stim szeto 	 * Port provider may have already called the buffer callback in
5017427fcaf8Stim szeto 	 * which case dbuf->db_xfer_start_timestamp will be 0.
5018427fcaf8Stim szeto 	 */
501940c3e8ffSJohn Forte 	if (ret != STMF_SUCCESS) {
502040c3e8ffSJohn Forte 		dbuf->db_flags &= ~DB_LPORT_XFER_ACTIVE;
502140c3e8ffSJohn Forte 		if (dbuf->db_xfer_start_timestamp != 0)
5022427fcaf8Stim szeto 			stmf_lport_xfer_done(itask, dbuf);
5023427fcaf8Stim szeto 	}
5024427fcaf8Stim szeto 
5025e17f3b22Stim szeto 	return (ret);
5026fcf3ce44SJohn Forte }
5027fcf3ce44SJohn Forte 
5028fcf3ce44SJohn Forte void
stmf_data_xfer_done(scsi_task_t * task,stmf_data_buf_t * dbuf,uint32_t iof)5029fcf3ce44SJohn Forte stmf_data_xfer_done(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t iof)
5030fcf3ce44SJohn Forte {
5031fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
5032fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
503340c3e8ffSJohn Forte 	stmf_i_local_port_t *ilport;
5034fcf3ce44SJohn Forte 	stmf_worker_t *w = itask->itask_worker;
503561dfa509SRick McNeal 	uint32_t new;
5036427fcaf8Stim szeto 	uint8_t update_queue_flags, free_it, queue_it;
5037427fcaf8Stim szeto 
5038427fcaf8Stim szeto 	stmf_lport_xfer_done(itask, dbuf);
5039fcf3ce44SJohn Forte 
504040c3e8ffSJohn Forte 	stmf_task_audit(itask, TE_XFER_DONE, iof, dbuf);
504140c3e8ffSJohn Forte 
504240c3e8ffSJohn Forte 	/* Guard against unexpected completions from the lport */
504340c3e8ffSJohn Forte 	if (dbuf->db_flags & DB_LPORT_XFER_ACTIVE) {
504440c3e8ffSJohn Forte 		dbuf->db_flags &= ~DB_LPORT_XFER_ACTIVE;
504540c3e8ffSJohn Forte 	} else {
504640c3e8ffSJohn Forte 		/*
504740c3e8ffSJohn Forte 		 * This should never happen.
504840c3e8ffSJohn Forte 		 */
504940c3e8ffSJohn Forte 		ilport = task->task_lport->lport_stmf_private;
505040c3e8ffSJohn Forte 		ilport->ilport_unexpected_comp++;
505140c3e8ffSJohn Forte 		cmn_err(CE_PANIC, "Unexpected xfer completion task %p dbuf %p",
505240c3e8ffSJohn Forte 		    (void *)task, (void *)dbuf);
505340c3e8ffSJohn Forte 		return;
505440c3e8ffSJohn Forte 	}
505540c3e8ffSJohn Forte 
505661dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
5057fcf3ce44SJohn Forte 	mutex_enter(&w->worker_lock);
505861dfa509SRick McNeal 	new = itask->itask_flags;
505961dfa509SRick McNeal 	if (itask->itask_flags & ITASK_BEING_ABORTED) {
5060fcf3ce44SJohn Forte 		mutex_exit(&w->worker_lock);
506161dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5062fcf3ce44SJohn Forte 		return;
5063fcf3ce44SJohn Forte 	}
5064fcf3ce44SJohn Forte 	free_it = 0;
5065fcf3ce44SJohn Forte 	if (iof & STMF_IOF_LPORT_DONE) {
5066fcf3ce44SJohn Forte 		new &= ~ITASK_KNOWN_TO_TGT_PORT;
5067fcf3ce44SJohn Forte 		task->task_completion_status = dbuf->db_xfer_status;
5068fcf3ce44SJohn Forte 		free_it = 1;
5069fcf3ce44SJohn Forte 	}
5070fcf3ce44SJohn Forte 	/*
5071fcf3ce44SJohn Forte 	 * If the task is known to LU then queue it. But if
5072fcf3ce44SJohn Forte 	 * it is already queued (multiple completions) then
5073fcf3ce44SJohn Forte 	 * just update the buffer information by grabbing the
5074fcf3ce44SJohn Forte 	 * worker lock. If the task is not known to LU,
5075fcf3ce44SJohn Forte 	 * completed/aborted, then see if we need to
5076fcf3ce44SJohn Forte 	 * free this task.
5077fcf3ce44SJohn Forte 	 */
507861dfa509SRick McNeal 	if (itask->itask_flags & ITASK_KNOWN_TO_LU) {
5079fcf3ce44SJohn Forte 		free_it = 0;
5080fcf3ce44SJohn Forte 		update_queue_flags = 1;
508161dfa509SRick McNeal 		if (itask->itask_flags & ITASK_IN_WORKER_QUEUE) {
5082fcf3ce44SJohn Forte 			queue_it = 0;
5083fcf3ce44SJohn Forte 		} else {
5084fcf3ce44SJohn Forte 			queue_it = 1;
5085fcf3ce44SJohn Forte 		}
5086fcf3ce44SJohn Forte 	} else {
5087fcf3ce44SJohn Forte 		update_queue_flags = 0;
5088fcf3ce44SJohn Forte 		queue_it = 0;
5089fcf3ce44SJohn Forte 	}
509061dfa509SRick McNeal 	itask->itask_flags = new;
5091fcf3ce44SJohn Forte 
5092fcf3ce44SJohn Forte 	if (update_queue_flags) {
5093fcf3ce44SJohn Forte 		uint8_t cmd = (dbuf->db_handle << 5) | ITASK_CMD_DATA_XFER_DONE;
5094fcf3ce44SJohn Forte 
509561dfa509SRick McNeal 		ASSERT((itask->itask_flags & ITASK_IN_FREE_LIST) == 0);
5096fcf3ce44SJohn Forte 		ASSERT(itask->itask_ncmds < ITASK_MAX_NCMDS);
509761dfa509SRick McNeal 
5098fcf3ce44SJohn Forte 		itask->itask_cmd_stack[itask->itask_ncmds++] = cmd;
5099fcf3ce44SJohn Forte 		if (queue_it) {
510061dfa509SRick McNeal 			STMF_ENQUEUE_ITASK(w, itask);
5101fcf3ce44SJohn Forte 		}
5102fcf3ce44SJohn Forte 		mutex_exit(&w->worker_lock);
510361dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
510461dfa509SRick McNeal 		return;
510561dfa509SRick McNeal 	}
5106fcf3ce44SJohn Forte 
510761dfa509SRick McNeal 	mutex_exit(&w->worker_lock);
5108fcf3ce44SJohn Forte 	if (free_it) {
5109fcf3ce44SJohn Forte 		if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
5110fcf3ce44SJohn Forte 		    ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
5111fcf3ce44SJohn Forte 		    ITASK_BEING_ABORTED)) == 0) {
5112fcf3ce44SJohn Forte 			stmf_task_free(task);
511361dfa509SRick McNeal 			return;
5114fcf3ce44SJohn Forte 		}
5115fcf3ce44SJohn Forte 	}
511661dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
5117fcf3ce44SJohn Forte }
5118fcf3ce44SJohn Forte 
5119fcf3ce44SJohn Forte stmf_status_t
stmf_send_scsi_status(scsi_task_t * task,uint32_t ioflags)5120fcf3ce44SJohn Forte stmf_send_scsi_status(scsi_task_t *task, uint32_t ioflags)
5121fcf3ce44SJohn Forte {
5122e17f3b22Stim szeto 	DTRACE_PROBE1(scsi__send__status, scsi_task_t *, task);
5123e17f3b22Stim szeto 
5124fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
5125fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
512640c3e8ffSJohn Forte 
512740c3e8ffSJohn Forte 	stmf_task_audit(itask, TE_SEND_STATUS, ioflags, NULL);
512840c3e8ffSJohn Forte 
512961dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
5130fcf3ce44SJohn Forte 	if (ioflags & STMF_IOF_LU_DONE) {
513161dfa509SRick McNeal 		if (itask->itask_flags & ITASK_BEING_ABORTED) {
513261dfa509SRick McNeal 			mutex_exit(&itask->itask_mutex);
5133fcf3ce44SJohn Forte 			return (STMF_ABORTED);
513461dfa509SRick McNeal 		}
513561dfa509SRick McNeal 		itask->itask_flags &= ~ITASK_KNOWN_TO_LU;
5136fcf3ce44SJohn Forte 	}
5137fcf3ce44SJohn Forte 
5138fcf3ce44SJohn Forte 	if (!(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT)) {
513961dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5140fcf3ce44SJohn Forte 		return (STMF_SUCCESS);
5141fcf3ce44SJohn Forte 	}
5142fcf3ce44SJohn Forte 
514361dfa509SRick McNeal 	if (itask->itask_flags & ITASK_BEING_ABORTED) {
514461dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5145fcf3ce44SJohn Forte 		return (STMF_ABORTED);
514661dfa509SRick McNeal 	}
514761dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
5148fcf3ce44SJohn Forte 
5149fcf3ce44SJohn Forte 	if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
5150fcf3ce44SJohn Forte 		task->task_status_ctrl = 0;
5151fcf3ce44SJohn Forte 		task->task_resid = 0;
5152fcf3ce44SJohn Forte 	} else if (task->task_cmd_xfer_length >
5153fcf3ce44SJohn Forte 	    task->task_expected_xfer_length) {
5154fcf3ce44SJohn Forte 		task->task_status_ctrl = TASK_SCTRL_OVER;
5155fcf3ce44SJohn Forte 		task->task_resid = task->task_cmd_xfer_length -
5156fcf3ce44SJohn Forte 		    task->task_expected_xfer_length;
5157fcf3ce44SJohn Forte 	} else if (task->task_nbytes_transferred <
5158fcf3ce44SJohn Forte 	    task->task_expected_xfer_length) {
5159fcf3ce44SJohn Forte 		task->task_status_ctrl = TASK_SCTRL_UNDER;
5160fcf3ce44SJohn Forte 		task->task_resid = task->task_expected_xfer_length -
5161fcf3ce44SJohn Forte 		    task->task_nbytes_transferred;
5162fcf3ce44SJohn Forte 	} else {
5163fcf3ce44SJohn Forte 		task->task_status_ctrl = 0;
5164fcf3ce44SJohn Forte 		task->task_resid = 0;
5165fcf3ce44SJohn Forte 	}
5166fcf3ce44SJohn Forte 	return (task->task_lport->lport_send_status(task, ioflags));
5167fcf3ce44SJohn Forte }
5168fcf3ce44SJohn Forte 
5169fcf3ce44SJohn Forte void
stmf_send_status_done(scsi_task_t * task,stmf_status_t s,uint32_t iof)5170fcf3ce44SJohn Forte stmf_send_status_done(scsi_task_t *task, stmf_status_t s, uint32_t iof)
5171fcf3ce44SJohn Forte {
5172fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
5173fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
5174fcf3ce44SJohn Forte 	stmf_worker_t *w = itask->itask_worker;
517561dfa509SRick McNeal 	uint32_t new;
5176427fcaf8Stim szeto 	uint8_t free_it, queue_it;
5177fcf3ce44SJohn Forte 
517840c3e8ffSJohn Forte 	stmf_task_audit(itask, TE_SEND_STATUS_DONE, iof, NULL);
517940c3e8ffSJohn Forte 
518061dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
5181fcf3ce44SJohn Forte 	mutex_enter(&w->worker_lock);
518261dfa509SRick McNeal 	new = itask->itask_flags;
518361dfa509SRick McNeal 	if (itask->itask_flags & ITASK_BEING_ABORTED) {
5184fcf3ce44SJohn Forte 		mutex_exit(&w->worker_lock);
518561dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5186fcf3ce44SJohn Forte 		return;
5187fcf3ce44SJohn Forte 	}
5188fcf3ce44SJohn Forte 	free_it = 0;
5189fcf3ce44SJohn Forte 	if (iof & STMF_IOF_LPORT_DONE) {
5190fcf3ce44SJohn Forte 		new &= ~ITASK_KNOWN_TO_TGT_PORT;
5191fcf3ce44SJohn Forte 		free_it = 1;
5192fcf3ce44SJohn Forte 	}
5193fcf3ce44SJohn Forte 	/*
5194fcf3ce44SJohn Forte 	 * If the task is known to LU then queue it. But if
5195fcf3ce44SJohn Forte 	 * it is already queued (multiple completions) then
5196fcf3ce44SJohn Forte 	 * just update the buffer information by grabbing the
5197fcf3ce44SJohn Forte 	 * worker lock. If the task is not known to LU,
5198fcf3ce44SJohn Forte 	 * completed/aborted, then see if we need to
5199fcf3ce44SJohn Forte 	 * free this task.
5200fcf3ce44SJohn Forte 	 */
520161dfa509SRick McNeal 	if (itask->itask_flags & ITASK_KNOWN_TO_LU) {
5202fcf3ce44SJohn Forte 		free_it = 0;
5203fcf3ce44SJohn Forte 		queue_it = 1;
520461dfa509SRick McNeal 		if (itask->itask_flags & ITASK_IN_WORKER_QUEUE) {
5205fcf3ce44SJohn Forte 			cmn_err(CE_PANIC, "status completion received"
5206fcf3ce44SJohn Forte 			    " when task is already in worker queue "
5207fcf3ce44SJohn Forte 			    " task = %p", (void *)task);
5208fcf3ce44SJohn Forte 		}
5209fcf3ce44SJohn Forte 	} else {
5210fcf3ce44SJohn Forte 		queue_it = 0;
5211fcf3ce44SJohn Forte 	}
521261dfa509SRick McNeal 	itask->itask_flags = new;
5213fcf3ce44SJohn Forte 	task->task_completion_status = s;
5214fcf3ce44SJohn Forte 
5215fcf3ce44SJohn Forte 	if (queue_it) {
5216fcf3ce44SJohn Forte 		ASSERT(itask->itask_ncmds < ITASK_MAX_NCMDS);
5217fcf3ce44SJohn Forte 		itask->itask_cmd_stack[itask->itask_ncmds++] =
5218fcf3ce44SJohn Forte 		    ITASK_CMD_STATUS_DONE;
521961dfa509SRick McNeal 
522061dfa509SRick McNeal 		STMF_ENQUEUE_ITASK(w, itask);
522161dfa509SRick McNeal 		mutex_exit(&w->worker_lock);
522261dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
522361dfa509SRick McNeal 		return;
5224fcf3ce44SJohn Forte 	}
522561dfa509SRick McNeal 
5226fcf3ce44SJohn Forte 	mutex_exit(&w->worker_lock);
5227fcf3ce44SJohn Forte 
5228fcf3ce44SJohn Forte 	if (free_it) {
5229fcf3ce44SJohn Forte 		if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
5230fcf3ce44SJohn Forte 		    ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
5231fcf3ce44SJohn Forte 		    ITASK_BEING_ABORTED)) == 0) {
5232fcf3ce44SJohn Forte 			stmf_task_free(task);
523361dfa509SRick McNeal 			return;
5234fcf3ce44SJohn Forte 		} else {
5235fcf3ce44SJohn Forte 			cmn_err(CE_PANIC, "LU is done with the task but LPORT "
5236437be372SJohn Forte 			    " is not done, itask %p itask_flags %x",
5237437be372SJohn Forte 			    (void *)itask, itask->itask_flags);
5238fcf3ce44SJohn Forte 		}
5239fcf3ce44SJohn Forte 	}
524061dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
5241fcf3ce44SJohn Forte }
5242fcf3ce44SJohn Forte 
5243fcf3ce44SJohn Forte void
stmf_task_lu_done(scsi_task_t * task)5244fcf3ce44SJohn Forte stmf_task_lu_done(scsi_task_t *task)
5245fcf3ce44SJohn Forte {
5246fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
5247fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
5248fcf3ce44SJohn Forte 	stmf_worker_t *w = itask->itask_worker;
5249fcf3ce44SJohn Forte 
525061dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
5251fcf3ce44SJohn Forte 	mutex_enter(&w->worker_lock);
525261dfa509SRick McNeal 	if (itask->itask_flags & ITASK_BEING_ABORTED) {
5253fcf3ce44SJohn Forte 		mutex_exit(&w->worker_lock);
525461dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5255fcf3ce44SJohn Forte 		return;
5256fcf3ce44SJohn Forte 	}
525761dfa509SRick McNeal 	if (itask->itask_flags & ITASK_IN_WORKER_QUEUE) {
5258fcf3ce44SJohn Forte 		cmn_err(CE_PANIC, "task_lu_done received"
5259fcf3ce44SJohn Forte 		    " when task is in worker queue "
5260fcf3ce44SJohn Forte 		    " task = %p", (void *)task);
5261fcf3ce44SJohn Forte 	}
526261dfa509SRick McNeal 	itask->itask_flags &= ~ITASK_KNOWN_TO_LU;
5263fcf3ce44SJohn Forte 
5264fcf3ce44SJohn Forte 	mutex_exit(&w->worker_lock);
5265fcf3ce44SJohn Forte 	if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
5266fcf3ce44SJohn Forte 	    ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
5267fcf3ce44SJohn Forte 	    ITASK_BEING_ABORTED)) == 0) {
5268fcf3ce44SJohn Forte 		stmf_task_free(task);
526961dfa509SRick McNeal 		return;
5270fcf3ce44SJohn Forte 	} else {
5271fcf3ce44SJohn Forte 		cmn_err(CE_PANIC, "stmf_lu_done should be the last stage but "
5272fcf3ce44SJohn Forte 		    " the task is still not done, task = %p", (void *)task);
5273fcf3ce44SJohn Forte 	}
527461dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
5275fcf3ce44SJohn Forte }
5276fcf3ce44SJohn Forte 
5277fcf3ce44SJohn Forte void
stmf_queue_task_for_abort(scsi_task_t * task,stmf_status_t s)5278fcf3ce44SJohn Forte stmf_queue_task_for_abort(scsi_task_t *task, stmf_status_t s)
5279fcf3ce44SJohn Forte {
5280fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
5281fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
5282fcf3ce44SJohn Forte 	stmf_worker_t *w;
5283fcf3ce44SJohn Forte 
528440c3e8ffSJohn Forte 	stmf_task_audit(itask, TE_TASK_ABORT, CMD_OR_IOF_NA, NULL);
528540c3e8ffSJohn Forte 
528661dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
528761dfa509SRick McNeal 	if ((itask->itask_flags & ITASK_BEING_ABORTED) ||
528861dfa509SRick McNeal 	    ((itask->itask_flags & (ITASK_KNOWN_TO_TGT_PORT |
5289fcf3ce44SJohn Forte 	    ITASK_KNOWN_TO_LU)) == 0)) {
529061dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5291fcf3ce44SJohn Forte 		return;
5292fcf3ce44SJohn Forte 	}
529361dfa509SRick McNeal 	itask->itask_flags |= ITASK_BEING_ABORTED;
5294fcf3ce44SJohn Forte 	task->task_completion_status = s;
5295fcf3ce44SJohn Forte 
5296fcf3ce44SJohn Forte 	if (((w = itask->itask_worker) == NULL) ||
5297fcf3ce44SJohn Forte 	    (itask->itask_flags & ITASK_IN_TRANSITION)) {
529861dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5299fcf3ce44SJohn Forte 		return;
5300fcf3ce44SJohn Forte 	}
5301fcf3ce44SJohn Forte 
5302fcf3ce44SJohn Forte 	/* Queue it and get out */
5303fcf3ce44SJohn Forte 	if (itask->itask_flags & ITASK_IN_WORKER_QUEUE) {
530461dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5305fcf3ce44SJohn Forte 		return;
5306fcf3ce44SJohn Forte 	}
530761dfa509SRick McNeal 	mutex_enter(&w->worker_lock);
530861dfa509SRick McNeal 	STMF_ENQUEUE_ITASK(w, itask);
5309fcf3ce44SJohn Forte 	mutex_exit(&w->worker_lock);
531061dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
5311fcf3ce44SJohn Forte }
5312fcf3ce44SJohn Forte 
5313fcf3ce44SJohn Forte void
stmf_abort(int abort_cmd,scsi_task_t * task,stmf_status_t s,void * arg)5314fcf3ce44SJohn Forte stmf_abort(int abort_cmd, scsi_task_t *task, stmf_status_t s, void *arg)
5315fcf3ce44SJohn Forte {
5316fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask = NULL;
531761dfa509SRick McNeal 	uint32_t f, rf;
5318fcf3ce44SJohn Forte 
5319e17f3b22Stim szeto 	DTRACE_PROBE2(scsi__task__abort, scsi_task_t *, task,
5320e17f3b22Stim szeto 	    stmf_status_t, s);
5321e17f3b22Stim szeto 
5322fcf3ce44SJohn Forte 	switch (abort_cmd) {
5323fcf3ce44SJohn Forte 	case STMF_QUEUE_ABORT_LU:
5324fcf3ce44SJohn Forte 		stmf_task_lu_killall((stmf_lu_t *)arg, task, s);
5325fcf3ce44SJohn Forte 		return;
5326fcf3ce44SJohn Forte 	case STMF_QUEUE_TASK_ABORT:
5327fcf3ce44SJohn Forte 		stmf_queue_task_for_abort(task, s);
5328fcf3ce44SJohn Forte 		return;
5329fcf3ce44SJohn Forte 	case STMF_REQUEUE_TASK_ABORT_LPORT:
5330fcf3ce44SJohn Forte 		rf = ITASK_TGT_PORT_ABORT_CALLED;
5331fcf3ce44SJohn Forte 		f = ITASK_KNOWN_TO_TGT_PORT;
5332fcf3ce44SJohn Forte 		break;
5333fcf3ce44SJohn Forte 	case STMF_REQUEUE_TASK_ABORT_LU:
5334fcf3ce44SJohn Forte 		rf = ITASK_LU_ABORT_CALLED;
5335fcf3ce44SJohn Forte 		f = ITASK_KNOWN_TO_LU;
5336fcf3ce44SJohn Forte 		break;
5337fcf3ce44SJohn Forte 	default:
5338fcf3ce44SJohn Forte 		return;
5339fcf3ce44SJohn Forte 	}
534061dfa509SRick McNeal 
5341fcf3ce44SJohn Forte 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
534261dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
5343fcf3ce44SJohn Forte 	f |= ITASK_BEING_ABORTED | rf;
534461dfa509SRick McNeal 
534561dfa509SRick McNeal 	if ((itask->itask_flags & f) != f) {
534661dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5347fcf3ce44SJohn Forte 		return;
5348fcf3ce44SJohn Forte 	}
534961dfa509SRick McNeal 	itask->itask_flags &= ~rf;
535061dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
535161dfa509SRick McNeal 
5352fcf3ce44SJohn Forte }
5353fcf3ce44SJohn Forte 
535461dfa509SRick McNeal /*
535561dfa509SRick McNeal  * NOTE: stmf_abort_task_offline will release and then reacquire the
535661dfa509SRick McNeal  * itask_mutex. This is required to prevent a lock order violation.
535761dfa509SRick McNeal  */
5358fcf3ce44SJohn Forte void
stmf_task_lu_aborted(scsi_task_t * task,stmf_status_t s,uint32_t iof)5359fcf3ce44SJohn Forte stmf_task_lu_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof)
5360fcf3ce44SJohn Forte {
5361fcf3ce44SJohn Forte 	char			 info[STMF_CHANGE_INFO_LEN];
5362fcf3ce44SJohn Forte 	stmf_i_scsi_task_t	*itask = TASK_TO_ITASK(task);
5363fcf3ce44SJohn Forte 	unsigned long long	st;
5364fcf3ce44SJohn Forte 
536540c3e8ffSJohn Forte 	stmf_task_audit(itask, TE_TASK_LU_ABORTED, iof, NULL);
536661dfa509SRick McNeal 	ASSERT(mutex_owned(&itask->itask_mutex));
5367fcf3ce44SJohn Forte 	st = s;	/* gcc fix */
5368fcf3ce44SJohn Forte 	if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) {
53694558d122SViswanathan Kannappan 		(void) snprintf(info, sizeof (info),
5370fcf3ce44SJohn Forte 		    "task %p, lu failed to abort ret=%llx", (void *)task, st);
5371fcf3ce44SJohn Forte 	} else if ((iof & STMF_IOF_LU_DONE) == 0) {
53724558d122SViswanathan Kannappan 		(void) snprintf(info, sizeof (info),
5373fcf3ce44SJohn Forte 		    "Task aborted but LU is not finished, task ="
5374fcf3ce44SJohn Forte 		    "%p, s=%llx, iof=%x", (void *)task, st, iof);
5375fcf3ce44SJohn Forte 	} else {
5376fcf3ce44SJohn Forte 		/*
5377fcf3ce44SJohn Forte 		 * LU abort successfully
5378fcf3ce44SJohn Forte 		 */
5379fcf3ce44SJohn Forte 		atomic_and_32(&itask->itask_flags, ~ITASK_KNOWN_TO_LU);
5380fcf3ce44SJohn Forte 		return;
5381fcf3ce44SJohn Forte 	}
5382fcf3ce44SJohn Forte 
5383fcf3ce44SJohn Forte 	stmf_abort_task_offline(task, 1, info);
5384fcf3ce44SJohn Forte }
5385fcf3ce44SJohn Forte 
538661dfa509SRick McNeal /*
538761dfa509SRick McNeal  * NOTE: stmf_abort_task_offline will release and then reacquire the
538861dfa509SRick McNeal  * itask_mutex. This is required to prevent a lock order violation.
538961dfa509SRick McNeal  */
5390fcf3ce44SJohn Forte void
stmf_task_lport_aborted(scsi_task_t * task,stmf_status_t s,uint32_t iof)5391fcf3ce44SJohn Forte stmf_task_lport_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof)
5392fcf3ce44SJohn Forte {
5393fcf3ce44SJohn Forte 	char			info[STMF_CHANGE_INFO_LEN];
5394fcf3ce44SJohn Forte 	stmf_i_scsi_task_t	*itask = TASK_TO_ITASK(task);
5395fcf3ce44SJohn Forte 	unsigned long long	st;
5396fcf3ce44SJohn Forte 
539761dfa509SRick McNeal 	ASSERT(mutex_owned(&itask->itask_mutex));
539840c3e8ffSJohn Forte 	stmf_task_audit(itask, TE_TASK_LPORT_ABORTED, iof, NULL);
5399fcf3ce44SJohn Forte 	st = s;
5400fcf3ce44SJohn Forte 	if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) {
54014558d122SViswanathan Kannappan 		(void) snprintf(info, sizeof (info),
5402fcf3ce44SJohn Forte 		    "task %p, tgt port failed to abort ret=%llx", (void *)task,
5403fcf3ce44SJohn Forte 		    st);
5404fcf3ce44SJohn Forte 	} else if ((iof & STMF_IOF_LPORT_DONE) == 0) {
54054558d122SViswanathan Kannappan 		(void) snprintf(info, sizeof (info),
5406fcf3ce44SJohn Forte 		    "Task aborted but tgt port is not finished, "
5407fcf3ce44SJohn Forte 		    "task=%p, s=%llx, iof=%x", (void *)task, st, iof);
5408fcf3ce44SJohn Forte 	} else {
5409fcf3ce44SJohn Forte 		/*
5410554c2b16Stim szeto 		 * LPORT abort successfully
5411fcf3ce44SJohn Forte 		 */
541261dfa509SRick McNeal 		atomic_and_32(&itask->itask_flags, ~ITASK_KNOWN_TO_TGT_PORT);
5413fcf3ce44SJohn Forte 		return;
5414fcf3ce44SJohn Forte 	}
5415fcf3ce44SJohn Forte 
5416fcf3ce44SJohn Forte 	stmf_abort_task_offline(task, 0, info);
5417fcf3ce44SJohn Forte }
5418fcf3ce44SJohn Forte 
541961dfa509SRick McNeal void
stmf_task_lport_aborted_unlocked(scsi_task_t * task,stmf_status_t s,uint32_t iof)542061dfa509SRick McNeal stmf_task_lport_aborted_unlocked(scsi_task_t *task, stmf_status_t s,
542161dfa509SRick McNeal     uint32_t iof)
542261dfa509SRick McNeal {
542361dfa509SRick McNeal 	stmf_i_scsi_task_t	*itask = TASK_TO_ITASK(task);
542461dfa509SRick McNeal 
542561dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
542661dfa509SRick McNeal 	stmf_task_lport_aborted(task, s, iof);
542761dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
542861dfa509SRick McNeal }
542961dfa509SRick McNeal 
5430fcf3ce44SJohn Forte stmf_status_t
stmf_task_poll_lu(scsi_task_t * task,uint32_t timeout)5431fcf3ce44SJohn Forte stmf_task_poll_lu(scsi_task_t *task, uint32_t timeout)
5432fcf3ce44SJohn Forte {
5433fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
5434fcf3ce44SJohn Forte 	    task->task_stmf_private;
5435fcf3ce44SJohn Forte 	stmf_worker_t *w = itask->itask_worker;
5436fcf3ce44SJohn Forte 	int i;
5437fcf3ce44SJohn Forte 
543861dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
5439fcf3ce44SJohn Forte 	ASSERT(itask->itask_flags & ITASK_KNOWN_TO_LU);
5440fcf3ce44SJohn Forte 	mutex_enter(&w->worker_lock);
5441fcf3ce44SJohn Forte 	if (itask->itask_ncmds >= ITASK_MAX_NCMDS) {
5442fcf3ce44SJohn Forte 		mutex_exit(&w->worker_lock);
544361dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5444fcf3ce44SJohn Forte 		return (STMF_BUSY);
5445fcf3ce44SJohn Forte 	}
5446fcf3ce44SJohn Forte 	for (i = 0; i < itask->itask_ncmds; i++) {
5447fcf3ce44SJohn Forte 		if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LU) {
5448fcf3ce44SJohn Forte 			mutex_exit(&w->worker_lock);
544961dfa509SRick McNeal 			mutex_exit(&itask->itask_mutex);
5450fcf3ce44SJohn Forte 			return (STMF_SUCCESS);
5451fcf3ce44SJohn Forte 		}
5452fcf3ce44SJohn Forte 	}
5453fcf3ce44SJohn Forte 	itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LU;
5454fcf3ce44SJohn Forte 	if (timeout == ITASK_DEFAULT_POLL_TIMEOUT) {
5455fcf3ce44SJohn Forte 		itask->itask_poll_timeout = ddi_get_lbolt() + 1;
5456fcf3ce44SJohn Forte 	} else {
5457fcf3ce44SJohn Forte 		clock_t t = drv_usectohz(timeout * 1000);
5458fcf3ce44SJohn Forte 		if (t == 0)
5459fcf3ce44SJohn Forte 			t = 1;
5460fcf3ce44SJohn Forte 		itask->itask_poll_timeout = ddi_get_lbolt() + t;
5461fcf3ce44SJohn Forte 	}
5462fcf3ce44SJohn Forte 	if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) {
546361dfa509SRick McNeal 		STMF_ENQUEUE_ITASK(w, itask);
5464fcf3ce44SJohn Forte 	}
5465fcf3ce44SJohn Forte 	mutex_exit(&w->worker_lock);
546661dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
5467fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
5468fcf3ce44SJohn Forte }
5469fcf3ce44SJohn Forte 
5470fcf3ce44SJohn Forte stmf_status_t
stmf_task_poll_lport(scsi_task_t * task,uint32_t timeout)5471fcf3ce44SJohn Forte stmf_task_poll_lport(scsi_task_t *task, uint32_t timeout)
5472fcf3ce44SJohn Forte {
5473fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
5474fcf3ce44SJohn Forte 	    task->task_stmf_private;
5475fcf3ce44SJohn Forte 	stmf_worker_t *w = itask->itask_worker;
5476fcf3ce44SJohn Forte 	int i;
5477fcf3ce44SJohn Forte 
547861dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
5479fcf3ce44SJohn Forte 	ASSERT(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT);
5480fcf3ce44SJohn Forte 	mutex_enter(&w->worker_lock);
5481fcf3ce44SJohn Forte 	if (itask->itask_ncmds >= ITASK_MAX_NCMDS) {
5482fcf3ce44SJohn Forte 		mutex_exit(&w->worker_lock);
548361dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
5484fcf3ce44SJohn Forte 		return (STMF_BUSY);
5485fcf3ce44SJohn Forte 	}
5486fcf3ce44SJohn Forte 	for (i = 0; i < itask->itask_ncmds; i++) {
5487fcf3ce44SJohn Forte 		if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LPORT) {
5488fcf3ce44SJohn Forte 			mutex_exit(&w->worker_lock);
548961dfa509SRick McNeal 			mutex_exit(&itask->itask_mutex);
5490fcf3ce44SJohn Forte 			return (STMF_SUCCESS);
5491fcf3ce44SJohn Forte 		}
5492fcf3ce44SJohn Forte 	}
5493fcf3ce44SJohn Forte 	itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LPORT;
5494fcf3ce44SJohn Forte 	if (timeout == ITASK_DEFAULT_POLL_TIMEOUT) {
5495fcf3ce44SJohn Forte 		itask->itask_poll_timeout = ddi_get_lbolt() + 1;
5496fcf3ce44SJohn Forte 	} else {
5497fcf3ce44SJohn Forte 		clock_t t = drv_usectohz(timeout * 1000);
5498fcf3ce44SJohn Forte 		if (t == 0)
5499fcf3ce44SJohn Forte 			t = 1;
5500fcf3ce44SJohn Forte 		itask->itask_poll_timeout = ddi_get_lbolt() + t;
5501fcf3ce44SJohn Forte 	}
5502fcf3ce44SJohn Forte 	if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) {
550361dfa509SRick McNeal 		STMF_ENQUEUE_ITASK(w, itask);
5504fcf3ce44SJohn Forte 	}
5505fcf3ce44SJohn Forte 	mutex_exit(&w->worker_lock);
550661dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
5507fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
5508fcf3ce44SJohn Forte }
5509fcf3ce44SJohn Forte 
5510fcf3ce44SJohn Forte void
stmf_do_task_abort(scsi_task_t * task)5511fcf3ce44SJohn Forte stmf_do_task_abort(scsi_task_t *task)
5512fcf3ce44SJohn Forte {
5513fcf3ce44SJohn Forte 	stmf_i_scsi_task_t	*itask = TASK_TO_ITASK(task);
5514fcf3ce44SJohn Forte 	stmf_lu_t		*lu;
5515fcf3ce44SJohn Forte 	stmf_local_port_t	*lport;
5516fcf3ce44SJohn Forte 	unsigned long long	 ret;
551761dfa509SRick McNeal 	uint32_t		 new = 0;
5518fcf3ce44SJohn Forte 	uint8_t			 call_lu_abort, call_port_abort;
5519fcf3ce44SJohn Forte 	char			 info[STMF_CHANGE_INFO_LEN];
5520fcf3ce44SJohn Forte 
5521fcf3ce44SJohn Forte 	lu = task->task_lu;
5522fcf3ce44SJohn Forte 	lport = task->task_lport;
552361dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
552461dfa509SRick McNeal 	new = itask->itask_flags;
552561dfa509SRick McNeal 	if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
552661dfa509SRick McNeal 	    ITASK_LU_ABORT_CALLED)) == ITASK_KNOWN_TO_LU) {
5527fcf3ce44SJohn Forte 		new |= ITASK_LU_ABORT_CALLED;
5528fcf3ce44SJohn Forte 		call_lu_abort = 1;
5529fcf3ce44SJohn Forte 	} else {
5530fcf3ce44SJohn Forte 		call_lu_abort = 0;
5531fcf3ce44SJohn Forte 	}
553261dfa509SRick McNeal 	itask->itask_flags = new;
5533fcf3ce44SJohn Forte 
5534fcf3ce44SJohn Forte 	if (call_lu_abort) {
5535fcf3ce44SJohn Forte 		if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0) {
5536fcf3ce44SJohn Forte 			ret = lu->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0);
5537fcf3ce44SJohn Forte 		} else {
5538fcf3ce44SJohn Forte 			ret = dlun0->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0);
5539fcf3ce44SJohn Forte 		}
5540fcf3ce44SJohn Forte 		if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) {
5541fcf3ce44SJohn Forte 			stmf_task_lu_aborted(task, ret, STMF_IOF_LU_DONE);
5542fcf3ce44SJohn Forte 		} else if (ret == STMF_BUSY) {
5543fcf3ce44SJohn Forte 			atomic_and_32(&itask->itask_flags,
5544fcf3ce44SJohn Forte 			    ~ITASK_LU_ABORT_CALLED);
5545fcf3ce44SJohn Forte 		} else if (ret != STMF_SUCCESS) {
55464558d122SViswanathan Kannappan 			(void) snprintf(info, sizeof (info),
5547fcf3ce44SJohn Forte 			    "Abort failed by LU %p, ret %llx", (void *)lu, ret);
5548fcf3ce44SJohn Forte 			stmf_abort_task_offline(task, 1, info);
5549fcf3ce44SJohn Forte 		}
5550fcf3ce44SJohn Forte 	} else if (itask->itask_flags & ITASK_KNOWN_TO_LU) {
5551fcf3ce44SJohn Forte 		if (ddi_get_lbolt() > (itask->itask_start_time +
5552fcf3ce44SJohn Forte 		    STMF_SEC2TICK(lu->lu_abort_timeout?
5553fcf3ce44SJohn Forte 		    lu->lu_abort_timeout : ITASK_DEFAULT_ABORT_TIMEOUT))) {
55544558d122SViswanathan Kannappan 			(void) snprintf(info, sizeof (info),
5555fcf3ce44SJohn Forte 			    "lu abort timed out");
5556fcf3ce44SJohn Forte 			stmf_abort_task_offline(itask->itask_task, 1, info);
5557fcf3ce44SJohn Forte 		}
5558fcf3ce44SJohn Forte 	}
5559fcf3ce44SJohn Forte 
556061dfa509SRick McNeal 	/*
556161dfa509SRick McNeal 	 * NOTE: After the call to either stmf_abort_task_offline() or
556261dfa509SRick McNeal 	 * stmf_task_lu_abort() the itask_mutex was dropped and reacquired
556361dfa509SRick McNeal 	 * to avoid a deadlock situation with stmf_state.stmf_lock.
556461dfa509SRick McNeal 	 */
556561dfa509SRick McNeal 
556661dfa509SRick McNeal 	new = itask->itask_flags;
556761dfa509SRick McNeal 	if ((itask->itask_flags & (ITASK_KNOWN_TO_TGT_PORT |
5568fcf3ce44SJohn Forte 	    ITASK_TGT_PORT_ABORT_CALLED)) == ITASK_KNOWN_TO_TGT_PORT) {
5569fcf3ce44SJohn Forte 		new |= ITASK_TGT_PORT_ABORT_CALLED;
5570fcf3ce44SJohn Forte 		call_port_abort = 1;
5571fcf3ce44SJohn Forte 	} else {
5572fcf3ce44SJohn Forte 		call_port_abort = 0;
5573fcf3ce44SJohn Forte 	}
557461dfa509SRick McNeal 	itask->itask_flags = new;
557561dfa509SRick McNeal 
5576fcf3ce44SJohn Forte 	if (call_port_abort) {
55775679c89fSjv227347 		ret = lport->lport_abort(lport, STMF_LPORT_ABORT_TASK, task, 0);
5578fcf3ce44SJohn Forte 		if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) {
5579fcf3ce44SJohn Forte 			stmf_task_lport_aborted(task, ret, STMF_IOF_LPORT_DONE);
5580fcf3ce44SJohn Forte 		} else if (ret == STMF_BUSY) {
5581fcf3ce44SJohn Forte 			atomic_and_32(&itask->itask_flags,
5582fcf3ce44SJohn Forte 			    ~ITASK_TGT_PORT_ABORT_CALLED);
5583fcf3ce44SJohn Forte 		} else if (ret != STMF_SUCCESS) {
55844558d122SViswanathan Kannappan 			(void) snprintf(info, sizeof (info),
5585fcf3ce44SJohn Forte 			    "Abort failed by tgt port %p ret %llx",
5586fcf3ce44SJohn Forte 			    (void *)lport, ret);
5587fcf3ce44SJohn Forte 			stmf_abort_task_offline(task, 0, info);
5588fcf3ce44SJohn Forte 		}
5589fcf3ce44SJohn Forte 	} else if (itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT) {
5590fcf3ce44SJohn Forte 		if (ddi_get_lbolt() > (itask->itask_start_time +
5591fcf3ce44SJohn Forte 		    STMF_SEC2TICK(lport->lport_abort_timeout?
5592fcf3ce44SJohn Forte 		    lport->lport_abort_timeout :
5593fcf3ce44SJohn Forte 		    ITASK_DEFAULT_ABORT_TIMEOUT))) {
55944558d122SViswanathan Kannappan 			(void) snprintf(info, sizeof (info),
5595fcf3ce44SJohn Forte 			    "lport abort timed out");
5596fcf3ce44SJohn Forte 			stmf_abort_task_offline(itask->itask_task, 0, info);
5597fcf3ce44SJohn Forte 		}
5598fcf3ce44SJohn Forte 	}
559961dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
5600fcf3ce44SJohn Forte }
5601fcf3ce44SJohn Forte 
5602fcf3ce44SJohn Forte stmf_status_t
stmf_ctl(int cmd,void * obj,void * arg)5603fcf3ce44SJohn Forte stmf_ctl(int cmd, void *obj, void *arg)
5604fcf3ce44SJohn Forte {
5605fcf3ce44SJohn Forte 	stmf_status_t			ret;
5606fcf3ce44SJohn Forte 	stmf_i_lu_t			*ilu;
5607fcf3ce44SJohn Forte 	stmf_i_local_port_t		*ilport;
5608fcf3ce44SJohn Forte 	stmf_state_change_info_t	*ssci = (stmf_state_change_info_t *)arg;
5609fcf3ce44SJohn Forte 
5610fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
5611fcf3ce44SJohn Forte 	ret = STMF_INVALID_ARG;
5612fcf3ce44SJohn Forte 	if (cmd & STMF_CMD_LU_OP) {
5613fcf3ce44SJohn Forte 		ilu = stmf_lookup_lu((stmf_lu_t *)obj);
5614fcf3ce44SJohn Forte 		if (ilu == NULL) {
5615fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
5616fcf3ce44SJohn Forte 		}
5617e17f3b22Stim szeto 		DTRACE_PROBE3(lu__state__change,
5618e17f3b22Stim szeto 		    stmf_lu_t *, ilu->ilu_lu,
5619e17f3b22Stim szeto 		    int, cmd, stmf_state_change_info_t *, ssci);
5620fcf3ce44SJohn Forte 	} else if (cmd & STMF_CMD_LPORT_OP) {
5621fcf3ce44SJohn Forte 		ilport = stmf_lookup_lport((stmf_local_port_t *)obj);
5622fcf3ce44SJohn Forte 		if (ilport == NULL) {
5623fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
5624fcf3ce44SJohn Forte 		}
5625e17f3b22Stim szeto 		DTRACE_PROBE3(lport__state__change,
5626e17f3b22Stim szeto 		    stmf_local_port_t *, ilport->ilport_lport,
5627e17f3b22Stim szeto 		    int, cmd, stmf_state_change_info_t *, ssci);
5628fcf3ce44SJohn Forte 	} else {
5629fcf3ce44SJohn Forte 		goto stmf_ctl_lock_exit;
5630fcf3ce44SJohn Forte 	}
5631fcf3ce44SJohn Forte 
5632fcf3ce44SJohn Forte 	switch (cmd) {
5633fcf3ce44SJohn Forte 	case STMF_CMD_LU_ONLINE:
56344f486358SNattuvetty Bhavyan 		switch (ilu->ilu_state) {
56354f486358SNattuvetty Bhavyan 			case STMF_STATE_OFFLINE:
56364f486358SNattuvetty Bhavyan 				ret = STMF_SUCCESS;
56374f486358SNattuvetty Bhavyan 				break;
56384f486358SNattuvetty Bhavyan 			case STMF_STATE_ONLINE:
56394f486358SNattuvetty Bhavyan 			case STMF_STATE_ONLINING:
5640fcf3ce44SJohn Forte 				ret = STMF_ALREADY;
56414f486358SNattuvetty Bhavyan 				break;
56424f486358SNattuvetty Bhavyan 			case STMF_STATE_OFFLINING:
56434f486358SNattuvetty Bhavyan 				ret = STMF_BUSY;
56444f486358SNattuvetty Bhavyan 				break;
56454f486358SNattuvetty Bhavyan 			default:
56464f486358SNattuvetty Bhavyan 				ret = STMF_BADSTATE;
56474f486358SNattuvetty Bhavyan 				break;
5648fcf3ce44SJohn Forte 		}
56494f486358SNattuvetty Bhavyan 		if (ret != STMF_SUCCESS)
5650fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
56514f486358SNattuvetty Bhavyan 
5652fcf3ce44SJohn Forte 		ilu->ilu_state = STMF_STATE_ONLINING;
5653fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
5654fcf3ce44SJohn Forte 		stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5655fcf3ce44SJohn Forte 		break;
5656fcf3ce44SJohn Forte 
5657fcf3ce44SJohn Forte 	case STMF_CMD_LU_ONLINE_COMPLETE:
5658fcf3ce44SJohn Forte 		if (ilu->ilu_state != STMF_STATE_ONLINING) {
56594f486358SNattuvetty Bhavyan 			ret = STMF_BADSTATE;
5660fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
5661fcf3ce44SJohn Forte 		}
5662fcf3ce44SJohn Forte 		if (((stmf_change_status_t *)arg)->st_completion_status ==
5663fcf3ce44SJohn Forte 		    STMF_SUCCESS) {
5664fcf3ce44SJohn Forte 			ilu->ilu_state = STMF_STATE_ONLINE;
5665fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
5666fcf3ce44SJohn Forte 			((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj,
5667fcf3ce44SJohn Forte 			    STMF_ACK_LU_ONLINE_COMPLETE, arg);
5668fcf3ce44SJohn Forte 			mutex_enter(&stmf_state.stmf_lock);
5669fcf3ce44SJohn Forte 			stmf_add_lu_to_active_sessions((stmf_lu_t *)obj);
5670fcf3ce44SJohn Forte 		} else {
5671fcf3ce44SJohn Forte 			/* XXX: should throw a meesage an record more data */
5672fcf3ce44SJohn Forte 			ilu->ilu_state = STMF_STATE_OFFLINE;
5673fcf3ce44SJohn Forte 		}
5674fcf3ce44SJohn Forte 		ret = STMF_SUCCESS;
5675fcf3ce44SJohn Forte 		goto stmf_ctl_lock_exit;
5676fcf3ce44SJohn Forte 
5677fcf3ce44SJohn Forte 	case STMF_CMD_LU_OFFLINE:
56784f486358SNattuvetty Bhavyan 		switch (ilu->ilu_state) {
56794f486358SNattuvetty Bhavyan 			case STMF_STATE_ONLINE:
56804f486358SNattuvetty Bhavyan 				ret = STMF_SUCCESS;
56814f486358SNattuvetty Bhavyan 				break;
56824f486358SNattuvetty Bhavyan 			case STMF_STATE_OFFLINE:
56834f486358SNattuvetty Bhavyan 			case STMF_STATE_OFFLINING:
5684fcf3ce44SJohn Forte 				ret = STMF_ALREADY;
56854f486358SNattuvetty Bhavyan 				break;
56864f486358SNattuvetty Bhavyan 			case STMF_STATE_ONLINING:
56874f486358SNattuvetty Bhavyan 				ret = STMF_BUSY;
56884f486358SNattuvetty Bhavyan 				break;
56894f486358SNattuvetty Bhavyan 			default:
56904f486358SNattuvetty Bhavyan 				ret = STMF_BADSTATE;
56914f486358SNattuvetty Bhavyan 				break;
5692fcf3ce44SJohn Forte 		}
56934f486358SNattuvetty Bhavyan 		if (ret != STMF_SUCCESS)
5694fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
5695fcf3ce44SJohn Forte 		ilu->ilu_state = STMF_STATE_OFFLINING;
5696fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
5697fcf3ce44SJohn Forte 		stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5698fcf3ce44SJohn Forte 		break;
5699fcf3ce44SJohn Forte 
5700fcf3ce44SJohn Forte 	case STMF_CMD_LU_OFFLINE_COMPLETE:
5701fcf3ce44SJohn Forte 		if (ilu->ilu_state != STMF_STATE_OFFLINING) {
57024f486358SNattuvetty Bhavyan 			ret = STMF_BADSTATE;
5703fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
5704fcf3ce44SJohn Forte 		}
5705fcf3ce44SJohn Forte 		if (((stmf_change_status_t *)arg)->st_completion_status ==
5706fcf3ce44SJohn Forte 		    STMF_SUCCESS) {
5707fcf3ce44SJohn Forte 			ilu->ilu_state = STMF_STATE_OFFLINE;
5708fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
5709fcf3ce44SJohn Forte 			((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj,
5710fcf3ce44SJohn Forte 			    STMF_ACK_LU_OFFLINE_COMPLETE, arg);
5711fcf3ce44SJohn Forte 			mutex_enter(&stmf_state.stmf_lock);
5712fcf3ce44SJohn Forte 		} else {
5713fcf3ce44SJohn Forte 			ilu->ilu_state = STMF_STATE_ONLINE;
5714fcf3ce44SJohn Forte 			stmf_add_lu_to_active_sessions((stmf_lu_t *)obj);
5715fcf3ce44SJohn Forte 		}
5716fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
5717fcf3ce44SJohn Forte 		break;
5718fcf3ce44SJohn Forte 
5719fcf3ce44SJohn Forte 	/*
5720fcf3ce44SJohn Forte 	 * LPORT_ONLINE/OFFLINE has nothing to do with link offline/online.
5721fcf3ce44SJohn Forte 	 * It's related with hardware disable/enable.
5722fcf3ce44SJohn Forte 	 */
5723fcf3ce44SJohn Forte 	case STMF_CMD_LPORT_ONLINE:
57244f486358SNattuvetty Bhavyan 		switch (ilport->ilport_state) {
57254f486358SNattuvetty Bhavyan 			case STMF_STATE_OFFLINE:
57264f486358SNattuvetty Bhavyan 				ret = STMF_SUCCESS;
57274f486358SNattuvetty Bhavyan 				break;
57284f486358SNattuvetty Bhavyan 			case STMF_STATE_ONLINE:
57294f486358SNattuvetty Bhavyan 			case STMF_STATE_ONLINING:
5730fcf3ce44SJohn Forte 				ret = STMF_ALREADY;
57314f486358SNattuvetty Bhavyan 				break;
57324f486358SNattuvetty Bhavyan 			case STMF_STATE_OFFLINING:
57334f486358SNattuvetty Bhavyan 				ret = STMF_BUSY;
57344f486358SNattuvetty Bhavyan 				break;
57354f486358SNattuvetty Bhavyan 			default:
57364f486358SNattuvetty Bhavyan 				ret = STMF_BADSTATE;
57374f486358SNattuvetty Bhavyan 				break;
5738fcf3ce44SJohn Forte 		}
57394f486358SNattuvetty Bhavyan 		if (ret != STMF_SUCCESS)
5740fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
5741fcf3ce44SJohn Forte 
5742fcf3ce44SJohn Forte 		/*
5743fcf3ce44SJohn Forte 		 * Only user request can recover the port from the
5744fcf3ce44SJohn Forte 		 * FORCED_OFFLINE state
5745fcf3ce44SJohn Forte 		 */
5746fcf3ce44SJohn Forte 		if (ilport->ilport_flags & ILPORT_FORCED_OFFLINE) {
5747fcf3ce44SJohn Forte 			if (!(ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) {
5748fcf3ce44SJohn Forte 				ret = STMF_FAILURE;
5749fcf3ce44SJohn Forte 				goto stmf_ctl_lock_exit;
5750fcf3ce44SJohn Forte 			}
5751fcf3ce44SJohn Forte 		}
5752fcf3ce44SJohn Forte 
5753fcf3ce44SJohn Forte 		/*
5754fcf3ce44SJohn Forte 		 * Avoid too frequent request to online
5755fcf3ce44SJohn Forte 		 */
5756fcf3ce44SJohn Forte 		if (ssci->st_rflags & STMF_RFLAG_USER_REQUEST) {
5757fcf3ce44SJohn Forte 			ilport->ilport_online_times = 0;
5758fcf3ce44SJohn Forte 			ilport->ilport_avg_interval = 0;
5759fcf3ce44SJohn Forte 		}
5760fcf3ce44SJohn Forte 		if ((ilport->ilport_avg_interval < STMF_AVG_ONLINE_INTERVAL) &&
5761fcf3ce44SJohn Forte 		    (ilport->ilport_online_times >= 4)) {
5762fcf3ce44SJohn Forte 			ret = STMF_FAILURE;
5763fcf3ce44SJohn Forte 			ilport->ilport_flags |= ILPORT_FORCED_OFFLINE;
5764fcf3ce44SJohn Forte 			stmf_trace(NULL, "stmf_ctl: too frequent request to "
5765fcf3ce44SJohn Forte 			    "online the port");
5766fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "stmf_ctl: too frequent request to "
5767fcf3ce44SJohn Forte 			    "online the port, set FORCED_OFFLINE now");
5768fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
5769fcf3ce44SJohn Forte 		}
5770fcf3ce44SJohn Forte 		if (ilport->ilport_online_times > 0) {
5771fcf3ce44SJohn Forte 			if (ilport->ilport_online_times == 1) {
5772fcf3ce44SJohn Forte 				ilport->ilport_avg_interval = ddi_get_lbolt() -
5773fcf3ce44SJohn Forte 				    ilport->ilport_last_online_clock;
5774fcf3ce44SJohn Forte 			} else {
5775fcf3ce44SJohn Forte 				ilport->ilport_avg_interval =
5776fcf3ce44SJohn Forte 				    (ilport->ilport_avg_interval +
5777fcf3ce44SJohn Forte 				    ddi_get_lbolt() -
5778fcf3ce44SJohn Forte 				    ilport->ilport_last_online_clock) >> 1;
5779fcf3ce44SJohn Forte 			}
5780fcf3ce44SJohn Forte 		}
5781fcf3ce44SJohn Forte 		ilport->ilport_last_online_clock = ddi_get_lbolt();
5782fcf3ce44SJohn Forte 		ilport->ilport_online_times++;
5783fcf3ce44SJohn Forte 
5784fcf3ce44SJohn Forte 		/*
5785fcf3ce44SJohn Forte 		 * Submit online service request
5786fcf3ce44SJohn Forte 		 */
5787fcf3ce44SJohn Forte 		ilport->ilport_flags &= ~ILPORT_FORCED_OFFLINE;
5788fcf3ce44SJohn Forte 		ilport->ilport_state = STMF_STATE_ONLINING;
5789fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
5790fcf3ce44SJohn Forte 		stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5791fcf3ce44SJohn Forte 		break;
5792fcf3ce44SJohn Forte 
5793fcf3ce44SJohn Forte 	case STMF_CMD_LPORT_ONLINE_COMPLETE:
5794fcf3ce44SJohn Forte 		if (ilport->ilport_state != STMF_STATE_ONLINING) {
57954f486358SNattuvetty Bhavyan 			ret = STMF_BADSTATE;
5796fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
5797fcf3ce44SJohn Forte 		}
5798fcf3ce44SJohn Forte 		if (((stmf_change_status_t *)arg)->st_completion_status ==
5799fcf3ce44SJohn Forte 		    STMF_SUCCESS) {
5800fcf3ce44SJohn Forte 			ilport->ilport_state = STMF_STATE_ONLINE;
5801fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
5802fcf3ce44SJohn Forte 			((stmf_local_port_t *)obj)->lport_ctl(
5803fcf3ce44SJohn Forte 			    (stmf_local_port_t *)obj,
5804fcf3ce44SJohn Forte 			    STMF_ACK_LPORT_ONLINE_COMPLETE, arg);
5805fcf3ce44SJohn Forte 			mutex_enter(&stmf_state.stmf_lock);
5806fcf3ce44SJohn Forte 		} else {
5807fcf3ce44SJohn Forte 			ilport->ilport_state = STMF_STATE_OFFLINE;
5808fcf3ce44SJohn Forte 		}
5809fcf3ce44SJohn Forte 		ret = STMF_SUCCESS;
5810fcf3ce44SJohn Forte 		goto stmf_ctl_lock_exit;
5811fcf3ce44SJohn Forte 
5812fcf3ce44SJohn Forte 	case STMF_CMD_LPORT_OFFLINE:
58134f486358SNattuvetty Bhavyan 		switch (ilport->ilport_state) {
58144f486358SNattuvetty Bhavyan 			case STMF_STATE_ONLINE:
58154f486358SNattuvetty Bhavyan 				ret = STMF_SUCCESS;
58164f486358SNattuvetty Bhavyan 				break;
58174f486358SNattuvetty Bhavyan 			case STMF_STATE_OFFLINE:
58184f486358SNattuvetty Bhavyan 			case STMF_STATE_OFFLINING:
5819fcf3ce44SJohn Forte 				ret = STMF_ALREADY;
58204f486358SNattuvetty Bhavyan 				break;
58214f486358SNattuvetty Bhavyan 			case STMF_STATE_ONLINING:
58224f486358SNattuvetty Bhavyan 				ret = STMF_BUSY;
58234f486358SNattuvetty Bhavyan 				break;
58244f486358SNattuvetty Bhavyan 			default:
58254f486358SNattuvetty Bhavyan 				ret = STMF_BADSTATE;
58264f486358SNattuvetty Bhavyan 				break;
5827fcf3ce44SJohn Forte 		}
58284f486358SNattuvetty Bhavyan 		if (ret != STMF_SUCCESS)
5829fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
58304f486358SNattuvetty Bhavyan 
5831fcf3ce44SJohn Forte 		ilport->ilport_state = STMF_STATE_OFFLINING;
5832fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
5833fcf3ce44SJohn Forte 		stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5834fcf3ce44SJohn Forte 		break;
5835fcf3ce44SJohn Forte 
5836fcf3ce44SJohn Forte 	case STMF_CMD_LPORT_OFFLINE_COMPLETE:
5837fcf3ce44SJohn Forte 		if (ilport->ilport_state != STMF_STATE_OFFLINING) {
58384f486358SNattuvetty Bhavyan 			ret = STMF_BADSTATE;
5839fcf3ce44SJohn Forte 			goto stmf_ctl_lock_exit;
5840fcf3ce44SJohn Forte 		}
5841fcf3ce44SJohn Forte 		if (((stmf_change_status_t *)arg)->st_completion_status ==
5842fcf3ce44SJohn Forte 		    STMF_SUCCESS) {
5843fcf3ce44SJohn Forte 			ilport->ilport_state = STMF_STATE_OFFLINE;
5844fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
5845fcf3ce44SJohn Forte 			((stmf_local_port_t *)obj)->lport_ctl(
5846fcf3ce44SJohn Forte 			    (stmf_local_port_t *)obj,
5847fcf3ce44SJohn Forte 			    STMF_ACK_LPORT_OFFLINE_COMPLETE, arg);
5848fcf3ce44SJohn Forte 			mutex_enter(&stmf_state.stmf_lock);
5849fcf3ce44SJohn Forte 		} else {
5850fcf3ce44SJohn Forte 			ilport->ilport_state = STMF_STATE_ONLINE;
5851fcf3ce44SJohn Forte 		}
5852fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
5853fcf3ce44SJohn Forte 		break;
5854fcf3ce44SJohn Forte 
5855fcf3ce44SJohn Forte 	default:
5856fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "Invalid ctl cmd received %x", cmd);
5857fcf3ce44SJohn Forte 		ret = STMF_INVALID_ARG;
5858fcf3ce44SJohn Forte 		goto stmf_ctl_lock_exit;
5859fcf3ce44SJohn Forte 	}
5860fcf3ce44SJohn Forte 
5861fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
5862fcf3ce44SJohn Forte 
5863fcf3ce44SJohn Forte stmf_ctl_lock_exit:;
5864fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
5865fcf3ce44SJohn Forte 	return (ret);
5866fcf3ce44SJohn Forte }
5867fcf3ce44SJohn Forte 
5868fcf3ce44SJohn Forte /* ARGSUSED */
5869fcf3ce44SJohn Forte stmf_status_t
stmf_info_impl(uint32_t cmd,void * arg1,void * arg2,uint8_t * buf,uint32_t * bufsizep)5870fcf3ce44SJohn Forte stmf_info_impl(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf,
5871fcf3ce44SJohn Forte     uint32_t *bufsizep)
5872fcf3ce44SJohn Forte {
5873fcf3ce44SJohn Forte 	return (STMF_NOT_SUPPORTED);
5874fcf3ce44SJohn Forte }
5875fcf3ce44SJohn Forte 
5876fcf3ce44SJohn Forte /* ARGSUSED */
5877fcf3ce44SJohn Forte stmf_status_t
stmf_info(uint32_t cmd,void * arg1,void * arg2,uint8_t * buf,uint32_t * bufsizep)5878fcf3ce44SJohn Forte stmf_info(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf,
5879fcf3ce44SJohn Forte     uint32_t *bufsizep)
5880fcf3ce44SJohn Forte {
5881fcf3ce44SJohn Forte 	uint32_t cl = SI_GET_CLASS(cmd);
5882fcf3ce44SJohn Forte 
5883fcf3ce44SJohn Forte 	if (cl == SI_STMF) {
5884fcf3ce44SJohn Forte 		return (stmf_info_impl(cmd, arg1, arg2, buf, bufsizep));
5885fcf3ce44SJohn Forte 	}
5886fcf3ce44SJohn Forte 	if (cl == SI_LPORT) {
58875679c89fSjv227347 		return (((stmf_local_port_t *)arg1)->lport_info(cmd, arg1,
58885679c89fSjv227347 		    arg2, buf, bufsizep));
5889fcf3ce44SJohn Forte 	} else if (cl == SI_LU) {
58905679c89fSjv227347 		return (((stmf_lu_t *)arg1)->lu_info(cmd, arg1, arg2, buf,
58915679c89fSjv227347 		    bufsizep));
5892fcf3ce44SJohn Forte 	}
5893fcf3ce44SJohn Forte 
5894fcf3ce44SJohn Forte 	return (STMF_NOT_SUPPORTED);
5895fcf3ce44SJohn Forte }
5896fcf3ce44SJohn Forte 
5897fcf3ce44SJohn Forte /*
589870c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States  * Used by port providers. pwwn is 8 byte wwn, sdid is the devid used by
5899fcf3ce44SJohn Forte  * stmf to register local ports. The ident should have 20 bytes in buffer
5900fcf3ce44SJohn Forte  * space to convert the wwn to "wwn.xxxxxxxxxxxxxxxx" string.
5901fcf3ce44SJohn Forte  */
5902fcf3ce44SJohn Forte void
stmf_wwn_to_devid_desc(scsi_devid_desc_t * sdid,uint8_t * wwn,uint8_t protocol_id)5903fcf3ce44SJohn Forte stmf_wwn_to_devid_desc(scsi_devid_desc_t *sdid, uint8_t *wwn,
5904fcf3ce44SJohn Forte     uint8_t protocol_id)
5905fcf3ce44SJohn Forte {
590670c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	char wwn_str[20+1];
590770c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States 
5908fcf3ce44SJohn Forte 	sdid->protocol_id = protocol_id;
5909fcf3ce44SJohn Forte 	sdid->piv = 1;
5910fcf3ce44SJohn Forte 	sdid->code_set = CODE_SET_ASCII;
5911fcf3ce44SJohn Forte 	sdid->association = ID_IS_TARGET_PORT;
5912fcf3ce44SJohn Forte 	sdid->ident_length = 20;
591370c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	/* Convert wwn value to "wwn.XXXXXXXXXXXXXXXX" format */
591470c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	(void) snprintf(wwn_str, sizeof (wwn_str),
5915fcf3ce44SJohn Forte 	    "wwn.%02X%02X%02X%02X%02X%02X%02X%02X",
5916fcf3ce44SJohn Forte 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
591770c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	bcopy(wwn_str, (char *)sdid->ident, 20);
5918fcf3ce44SJohn Forte }
5919fcf3ce44SJohn Forte 
592070c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States 
5921fcf3ce44SJohn Forte stmf_xfer_data_t *
stmf_prepare_tpgs_data(uint8_t ilu_alua)592245039663SJohn Forte stmf_prepare_tpgs_data(uint8_t ilu_alua)
5923fcf3ce44SJohn Forte {
5924fcf3ce44SJohn Forte 	stmf_xfer_data_t *xd;
5925fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
5926fcf3ce44SJohn Forte 	uint8_t *p;
592745039663SJohn Forte 	uint32_t sz, asz, nports = 0, nports_standby = 0;
5928fcf3ce44SJohn Forte 
5929fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
593045039663SJohn Forte 	/* check if any ports are standby and create second group */
593161dfa509SRick McNeal 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
593245039663SJohn Forte 	    ilport = ilport->ilport_next) {
593345039663SJohn Forte 		if (ilport->ilport_standby == 1) {
593445039663SJohn Forte 			nports_standby++;
593545039663SJohn Forte 		} else {
593645039663SJohn Forte 			nports++;
593745039663SJohn Forte 		}
593845039663SJohn Forte 	}
593945039663SJohn Forte 
594061dfa509SRick McNeal 	/*
594161dfa509SRick McNeal 	 * Section 6.25 REPORT TARGET PORT GROUPS
594261dfa509SRick McNeal 	 * The reply can contain many group replies. Each group is limited
594361dfa509SRick McNeal 	 * to 255 port identifiers so we'll need to limit the amount of
594461dfa509SRick McNeal 	 * data returned. For FC ports there's a physical limitation in
594561dfa509SRick McNeal 	 * machines that make reaching 255 ports very, very unlikely. For
594661dfa509SRick McNeal 	 * iSCSI on the other hand recent changes mean the port count could
594761dfa509SRick McNeal 	 * be as high as 4096 (current limit). Limiting the data returned
594861dfa509SRick McNeal 	 * for iSCSI isn't as bad as it sounds. This information is only
594961dfa509SRick McNeal 	 * important for ALUA, which isn't supported for iSCSI. iSCSI uses
595061dfa509SRick McNeal 	 * virtual IP addresses to deal with node fail over in a cluster.
595161dfa509SRick McNeal 	 */
595245039663SJohn Forte 	nports = min(nports, 255);
595345039663SJohn Forte 	nports_standby = min(nports_standby, 255);
595461dfa509SRick McNeal 
595561dfa509SRick McNeal 	/*
595661dfa509SRick McNeal 	 * The first 4 bytes of the returned data is the length. The
595761dfa509SRick McNeal 	 * size of the Target Port Group header is 8 bytes. So, that's where
595861dfa509SRick McNeal 	 * the 12 comes from. Each port entry is 4 bytes in size.
595961dfa509SRick McNeal 	 */
5960fcf3ce44SJohn Forte 	sz = (nports * 4) + 12;
596161dfa509SRick McNeal 	if (nports_standby != 0 && ilu_alua != 0) {
596261dfa509SRick McNeal 		/* --- Only add 8 bytes since it's just the Group header ---- */
596345039663SJohn Forte 		sz += (nports_standby * 4) + 8;
596445039663SJohn Forte 	}
596561dfa509SRick McNeal 
596661dfa509SRick McNeal 	/*
596761dfa509SRick McNeal 	 * The stmf_xfer_data structure contains 4 bytes that will be
596861dfa509SRick McNeal 	 * part of the data buffer. So, subtract the 4 bytes from the space
596961dfa509SRick McNeal 	 * needed.
597061dfa509SRick McNeal 	 */
597161dfa509SRick McNeal 	asz = sizeof (*xd) + sz - 4;
5972fcf3ce44SJohn Forte 	xd = (stmf_xfer_data_t *)kmem_zalloc(asz, KM_NOSLEEP);
5973fcf3ce44SJohn Forte 	if (xd == NULL) {
5974fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
5975fcf3ce44SJohn Forte 		return (NULL);
5976fcf3ce44SJohn Forte 	}
5977fcf3ce44SJohn Forte 	xd->alloc_size = asz;
5978fcf3ce44SJohn Forte 	xd->size_left = sz;
5979fcf3ce44SJohn Forte 
5980fcf3ce44SJohn Forte 	p = xd->buf;
5981fcf3ce44SJohn Forte 
598261dfa509SRick McNeal 	/* ---- length values never include the field that holds the size --- */
5983fcf3ce44SJohn Forte 	*((uint32_t *)p) = BE_32(sz - 4);
5984fcf3ce44SJohn Forte 	p += 4;
598561dfa509SRick McNeal 
598661dfa509SRick McNeal 	/* ---- Now fill out the first Target Group header ---- */
5987fcf3ce44SJohn Forte 	p[0] = 0x80;	/* PREF */
598845039663SJohn Forte 	p[1] = 5;	/* AO_SUP, S_SUP */
598945039663SJohn Forte 	if (stmf_state.stmf_alua_node == 1) {
599045039663SJohn Forte 		p[3] = 1;	/* Group 1 */
599145039663SJohn Forte 	} else {
599245039663SJohn Forte 		p[3] = 0;	/* Group 0 */
599345039663SJohn Forte 	}
5994fcf3ce44SJohn Forte 	p[7] = nports & 0xff;
5995fcf3ce44SJohn Forte 	p += 8;
599661dfa509SRick McNeal 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL && nports != 0;
599745039663SJohn Forte 	    ilport = ilport->ilport_next) {
599845039663SJohn Forte 		if (ilport->ilport_standby == 1) {
599945039663SJohn Forte 			continue;
6000fcf3ce44SJohn Forte 		}
600145039663SJohn Forte 		((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid);
600245039663SJohn Forte 		p += 4;
600361dfa509SRick McNeal 		nports--;
600445039663SJohn Forte 	}
600561dfa509SRick McNeal 	if (nports_standby != 0 && ilu_alua != 0) {
600645039663SJohn Forte 		p[0] = 0x02;	/* Non PREF, Standby */
600745039663SJohn Forte 		p[1] = 5;	/* AO_SUP, S_SUP */
600845039663SJohn Forte 		if (stmf_state.stmf_alua_node == 1) {
600945039663SJohn Forte 			p[3] = 0;	/* Group 0 */
601045039663SJohn Forte 		} else {
601145039663SJohn Forte 			p[3] = 1;	/* Group 1 */
601245039663SJohn Forte 		}
601345039663SJohn Forte 		p[7] = nports_standby & 0xff;
601445039663SJohn Forte 		p += 8;
601561dfa509SRick McNeal 		for (ilport = stmf_state.stmf_ilportlist; ilport != NULL &&
601661dfa509SRick McNeal 		    nports_standby != 0; ilport = ilport->ilport_next) {
601745039663SJohn Forte 			if (ilport->ilport_standby == 0) {
601845039663SJohn Forte 				continue;
601945039663SJohn Forte 			}
602045039663SJohn Forte 			((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid);
602145039663SJohn Forte 			p += 4;
602261dfa509SRick McNeal 			nports_standby--;
602345039663SJohn Forte 		}
602445039663SJohn Forte 	}
602545039663SJohn Forte 
6026fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
6027fcf3ce44SJohn Forte 
6028fcf3ce44SJohn Forte 	return (xd);
6029fcf3ce44SJohn Forte }
6030fcf3ce44SJohn Forte 
60318fe96085Stim szeto struct scsi_devid_desc *
stmf_scsilib_get_devid_desc(uint16_t rtpid)60328fe96085Stim szeto stmf_scsilib_get_devid_desc(uint16_t rtpid)
60338fe96085Stim szeto {
60348fe96085Stim szeto 	scsi_devid_desc_t *devid = NULL;
60358fe96085Stim szeto 	stmf_i_local_port_t *ilport;
60368fe96085Stim szeto 
60378fe96085Stim szeto 	mutex_enter(&stmf_state.stmf_lock);
60388fe96085Stim szeto 
60398fe96085Stim szeto 	for (ilport = stmf_state.stmf_ilportlist; ilport;
60408fe96085Stim szeto 	    ilport = ilport->ilport_next) {
60418fe96085Stim szeto 		if (ilport->ilport_rtpid == rtpid) {
60428fe96085Stim szeto 			scsi_devid_desc_t *id = ilport->ilport_lport->lport_id;
6043716c1805SNattuvetty Bhavyan 			uint32_t id_sz = sizeof (scsi_devid_desc_t) +
60448fe96085Stim szeto 			    id->ident_length;
60458fe96085Stim szeto 			devid = (scsi_devid_desc_t *)kmem_zalloc(id_sz,
60468fe96085Stim szeto 			    KM_NOSLEEP);
60478fe96085Stim szeto 			if (devid != NULL) {
60488fe96085Stim szeto 				bcopy(id, devid, id_sz);
60498fe96085Stim szeto 			}
60508fe96085Stim szeto 			break;
60518fe96085Stim szeto 		}
60528fe96085Stim szeto 	}
60538fe96085Stim szeto 
60548fe96085Stim szeto 	mutex_exit(&stmf_state.stmf_lock);
60558fe96085Stim szeto 	return (devid);
60568fe96085Stim szeto }
60578fe96085Stim szeto 
60588fe96085Stim szeto uint16_t
stmf_scsilib_get_lport_rtid(struct scsi_devid_desc * devid)60598fe96085Stim szeto stmf_scsilib_get_lport_rtid(struct scsi_devid_desc *devid)
60608fe96085Stim szeto {
60618fe96085Stim szeto 	stmf_i_local_port_t	*ilport;
60628fe96085Stim szeto 	scsi_devid_desc_t	*id;
60638fe96085Stim szeto 	uint16_t		rtpid = 0;
60648fe96085Stim szeto 
60658fe96085Stim szeto 	mutex_enter(&stmf_state.stmf_lock);
60668fe96085Stim szeto 	for (ilport = stmf_state.stmf_ilportlist; ilport;
60678fe96085Stim szeto 	    ilport = ilport->ilport_next) {
60688fe96085Stim szeto 		id = ilport->ilport_lport->lport_id;
60698fe96085Stim szeto 		if ((devid->ident_length == id->ident_length) &&
60708fe96085Stim szeto 		    (memcmp(devid->ident, id->ident, id->ident_length) == 0)) {
60718fe96085Stim szeto 			rtpid = ilport->ilport_rtpid;
60728fe96085Stim szeto 			break;
60738fe96085Stim szeto 		}
60748fe96085Stim szeto 	}
60758fe96085Stim szeto 	mutex_exit(&stmf_state.stmf_lock);
60768fe96085Stim szeto 	return (rtpid);
60778fe96085Stim szeto }
6078fcf3ce44SJohn Forte 
6079fcf3ce44SJohn Forte static uint16_t stmf_lu_id_gen_number = 0;
6080fcf3ce44SJohn Forte 
6081fcf3ce44SJohn Forte stmf_status_t
stmf_scsilib_uniq_lu_id(uint32_t company_id,scsi_devid_desc_t * lu_id)6082fcf3ce44SJohn Forte stmf_scsilib_uniq_lu_id(uint32_t company_id, scsi_devid_desc_t *lu_id)
6083fcf3ce44SJohn Forte {
6084fdcc480aSJohn Forte 	return (stmf_scsilib_uniq_lu_id2(company_id, 0, lu_id));
6085fdcc480aSJohn Forte }
6086fdcc480aSJohn Forte 
6087fdcc480aSJohn Forte stmf_status_t
stmf_scsilib_uniq_lu_id2(uint32_t company_id,uint32_t host_id,scsi_devid_desc_t * lu_id)6088fdcc480aSJohn Forte stmf_scsilib_uniq_lu_id2(uint32_t company_id, uint32_t host_id,
6089fdcc480aSJohn Forte     scsi_devid_desc_t *lu_id)
6090fdcc480aSJohn Forte {
6091fcf3ce44SJohn Forte 	uint8_t *p;
6092fcf3ce44SJohn Forte 	struct timeval32 timestamp32;
6093fcf3ce44SJohn Forte 	uint32_t *t = (uint32_t *)&timestamp32;
6094fcf3ce44SJohn Forte 	struct ether_addr mac;
6095fcf3ce44SJohn Forte 	uint8_t *e = (uint8_t *)&mac;
6096fdcc480aSJohn Forte 	int hid = (int)host_id;
609757ff5e7eSJeff Biseda 	uint16_t gen_number;
6098fcf3ce44SJohn Forte 
6099fcf3ce44SJohn Forte 	if (company_id == COMPANY_ID_NONE)
6100fcf3ce44SJohn Forte 		company_id = COMPANY_ID_SUN;
6101fcf3ce44SJohn Forte 
6102fcf3ce44SJohn Forte 	if (lu_id->ident_length != 0x10)
6103fcf3ce44SJohn Forte 		return (STMF_INVALID_ARG);
6104fcf3ce44SJohn Forte 
6105fcf3ce44SJohn Forte 	p = (uint8_t *)lu_id;
6106fcf3ce44SJohn Forte 
61071a5e258fSJosef 'Jeff' Sipek 	gen_number = atomic_inc_16_nv(&stmf_lu_id_gen_number);
6108fcf3ce44SJohn Forte 
6109fcf3ce44SJohn Forte 	p[0] = 0xf1; p[1] = 3; p[2] = 0; p[3] = 0x10;
6110fcf3ce44SJohn Forte 	p[4] = ((company_id >> 20) & 0xf) | 0x60;
6111fcf3ce44SJohn Forte 	p[5] = (company_id >> 12) & 0xff;
6112fcf3ce44SJohn Forte 	p[6] = (company_id >> 4) & 0xff;
6113fcf3ce44SJohn Forte 	p[7] = (company_id << 4) & 0xf0;
6114fdcc480aSJohn Forte 	if (hid == 0 && !localetheraddr((struct ether_addr *)NULL, &mac)) {
6115fdcc480aSJohn Forte 		hid = BE_32((int)zone_get_hostid(NULL));
6116fdcc480aSJohn Forte 	}
6117fdcc480aSJohn Forte 	if (hid != 0) {
6118fcf3ce44SJohn Forte 		e[0] = (hid >> 24) & 0xff;
6119fcf3ce44SJohn Forte 		e[1] = (hid >> 16) & 0xff;
6120fcf3ce44SJohn Forte 		e[2] = (hid >> 8) & 0xff;
6121fcf3ce44SJohn Forte 		e[3] = hid & 0xff;
6122fcf3ce44SJohn Forte 		e[4] = e[5] = 0;
6123fcf3ce44SJohn Forte 	}
6124fcf3ce44SJohn Forte 	bcopy(e, p+8, 6);
6125fcf3ce44SJohn Forte 	uniqtime32(&timestamp32);
6126fcf3ce44SJohn Forte 	*t = BE_32(*t);
6127fcf3ce44SJohn Forte 	bcopy(t, p+14, 4);
612857ff5e7eSJeff Biseda 	p[18] = (gen_number >> 8) & 0xff;
612957ff5e7eSJeff Biseda 	p[19] = gen_number & 0xff;
6130fcf3ce44SJohn Forte 
6131fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
6132fcf3ce44SJohn Forte }
6133fcf3ce44SJohn Forte 
6134fcf3ce44SJohn Forte /*
6135fcf3ce44SJohn Forte  * saa is sense key, ASC, ASCQ
6136fcf3ce44SJohn Forte  */
6137fcf3ce44SJohn Forte void
stmf_scsilib_send_status(scsi_task_t * task,uint8_t st,uint32_t saa)6138fcf3ce44SJohn Forte stmf_scsilib_send_status(scsi_task_t *task, uint8_t st, uint32_t saa)
6139fcf3ce44SJohn Forte {
6140fcf3ce44SJohn Forte 	uint8_t sd[18];
6141fcf3ce44SJohn Forte 	task->task_scsi_status = st;
6142fcf3ce44SJohn Forte 	if (st == 2) {
6143fcf3ce44SJohn Forte 		bzero(sd, 18);
6144fcf3ce44SJohn Forte 		sd[0] = 0x70;
6145fcf3ce44SJohn Forte 		sd[2] = (saa >> 16) & 0xf;
6146fcf3ce44SJohn Forte 		sd[7] = 10;
6147fcf3ce44SJohn Forte 		sd[12] = (saa >> 8) & 0xff;
6148fcf3ce44SJohn Forte 		sd[13] = saa & 0xff;
6149fcf3ce44SJohn Forte 		task->task_sense_data = sd;
6150fcf3ce44SJohn Forte 		task->task_sense_length = 18;
6151fcf3ce44SJohn Forte 	} else {
6152fcf3ce44SJohn Forte 		task->task_sense_data = NULL;
6153fcf3ce44SJohn Forte 		task->task_sense_length = 0;
6154fcf3ce44SJohn Forte 	}
6155fcf3ce44SJohn Forte 	(void) stmf_send_scsi_status(task, STMF_IOF_LU_DONE);
6156fcf3ce44SJohn Forte }
6157fcf3ce44SJohn Forte 
6158fcf3ce44SJohn Forte uint32_t
stmf_scsilib_prepare_vpd_page83(scsi_task_t * task,uint8_t * page,uint32_t page_len,uint8_t byte0,uint32_t vpd_mask)6159fcf3ce44SJohn Forte stmf_scsilib_prepare_vpd_page83(scsi_task_t *task, uint8_t *page,
6160fcf3ce44SJohn Forte     uint32_t page_len, uint8_t byte0, uint32_t vpd_mask)
6161fcf3ce44SJohn Forte {
6162fcf3ce44SJohn Forte 	uint8_t		*p = NULL;
6163fcf3ce44SJohn Forte 	uint8_t		small_buf[32];
6164fcf3ce44SJohn Forte 	uint32_t	sz = 0;
6165fcf3ce44SJohn Forte 	uint32_t	n = 4;
6166fcf3ce44SJohn Forte 	uint32_t	m = 0;
6167fcf3ce44SJohn Forte 	uint32_t	last_bit = 0;
6168fcf3ce44SJohn Forte 
6169fcf3ce44SJohn Forte 	if (page_len < 4)
6170fcf3ce44SJohn Forte 		return (0);
6171fcf3ce44SJohn Forte 	if (page_len > 65535)
6172fcf3ce44SJohn Forte 		page_len = 65535;
6173fcf3ce44SJohn Forte 
6174fcf3ce44SJohn Forte 	page[0] = byte0;
6175fcf3ce44SJohn Forte 	page[1] = 0x83;
6176fcf3ce44SJohn Forte 
6177fcf3ce44SJohn Forte 	/* CONSTCOND */
6178fcf3ce44SJohn Forte 	while (1) {
6179fcf3ce44SJohn Forte 		m += sz;
6180fcf3ce44SJohn Forte 		if (sz && (page_len > n)) {
6181fcf3ce44SJohn Forte 			uint32_t copysz;
6182fcf3ce44SJohn Forte 			copysz = page_len > (n + sz) ? sz : page_len - n;
6183fcf3ce44SJohn Forte 			bcopy(p, page + n, copysz);
6184fcf3ce44SJohn Forte 			n += copysz;
6185fcf3ce44SJohn Forte 		}
6186fcf3ce44SJohn Forte 		vpd_mask &= ~last_bit;
6187fcf3ce44SJohn Forte 		if (vpd_mask == 0)
6188fcf3ce44SJohn Forte 			break;
6189fcf3ce44SJohn Forte 
6190fcf3ce44SJohn Forte 		if (vpd_mask & STMF_VPD_LU_ID) {
6191fcf3ce44SJohn Forte 			last_bit = STMF_VPD_LU_ID;
6192fcf3ce44SJohn Forte 			sz = task->task_lu->lu_id->ident_length + 4;
6193fcf3ce44SJohn Forte 			p = (uint8_t *)task->task_lu->lu_id;
6194fcf3ce44SJohn Forte 			continue;
6195fcf3ce44SJohn Forte 		} else if (vpd_mask & STMF_VPD_TARGET_ID) {
6196fcf3ce44SJohn Forte 			last_bit = STMF_VPD_TARGET_ID;
6197fcf3ce44SJohn Forte 			sz = task->task_lport->lport_id->ident_length + 4;
6198fcf3ce44SJohn Forte 			p = (uint8_t *)task->task_lport->lport_id;
6199fcf3ce44SJohn Forte 			continue;
6200fcf3ce44SJohn Forte 		} else if (vpd_mask & STMF_VPD_TP_GROUP) {
620145039663SJohn Forte 			stmf_i_local_port_t *ilport;
6202fcf3ce44SJohn Forte 			last_bit = STMF_VPD_TP_GROUP;
6203fcf3ce44SJohn Forte 			p = small_buf;
6204fcf3ce44SJohn Forte 			bzero(p, 8);
6205fcf3ce44SJohn Forte 			p[0] = 1;
6206fcf3ce44SJohn Forte 			p[1] = 0x15;
6207fcf3ce44SJohn Forte 			p[3] = 4;
620845039663SJohn Forte 			ilport = (stmf_i_local_port_t *)
620945039663SJohn Forte 			    task->task_lport->lport_stmf_private;
621094d9b8e1SJohn Forte 			/*
621194d9b8e1SJohn Forte 			 * If we're in alua mode, group 1 contains all alua
621294d9b8e1SJohn Forte 			 * participating ports and all standby ports
621394d9b8e1SJohn Forte 			 * > 255. Otherwise, if we're in alua mode, any local
621494d9b8e1SJohn Forte 			 * ports (non standby/pppt) are also in group 1 if the
621594d9b8e1SJohn Forte 			 * alua node is 1. Otherwise the group is 0.
621694d9b8e1SJohn Forte 			 */
621794d9b8e1SJohn Forte 			if ((stmf_state.stmf_alua_state &&
621894d9b8e1SJohn Forte 			    (ilport->ilport_alua || ilport->ilport_standby) &&
621994d9b8e1SJohn Forte 			    ilport->ilport_rtpid > 255) ||
622094d9b8e1SJohn Forte 			    (stmf_state.stmf_alua_node == 1 &&
622194d9b8e1SJohn Forte 			    ilport->ilport_standby != 1)) {
622245039663SJohn Forte 				p[7] = 1;	/* Group 1 */
622345039663SJohn Forte 			}
6224fcf3ce44SJohn Forte 			sz = 8;
6225fcf3ce44SJohn Forte 			continue;
6226fcf3ce44SJohn Forte 		} else if (vpd_mask & STMF_VPD_RELATIVE_TP_ID) {
6227fcf3ce44SJohn Forte 			stmf_i_local_port_t *ilport;
6228fcf3ce44SJohn Forte 
6229fcf3ce44SJohn Forte 			last_bit = STMF_VPD_RELATIVE_TP_ID;
6230fcf3ce44SJohn Forte 			p = small_buf;
6231fcf3ce44SJohn Forte 			bzero(p, 8);
6232fcf3ce44SJohn Forte 			p[0] = 1;
6233fcf3ce44SJohn Forte 			p[1] = 0x14;
6234fcf3ce44SJohn Forte 			p[3] = 4;
6235fcf3ce44SJohn Forte 			ilport = (stmf_i_local_port_t *)
6236fcf3ce44SJohn Forte 			    task->task_lport->lport_stmf_private;
6237fcf3ce44SJohn Forte 			p[6] = (ilport->ilport_rtpid >> 8) & 0xff;
6238fcf3ce44SJohn Forte 			p[7] = ilport->ilport_rtpid & 0xff;
6239fcf3ce44SJohn Forte 			sz = 8;
6240fcf3ce44SJohn Forte 			continue;
6241fcf3ce44SJohn Forte 		} else {
6242fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "Invalid vpd_mask");
6243fcf3ce44SJohn Forte 			break;
6244fcf3ce44SJohn Forte 		}
6245fcf3ce44SJohn Forte 	}
6246fcf3ce44SJohn Forte 
6247fcf3ce44SJohn Forte 	page[2] = (m >> 8) & 0xff;
6248fcf3ce44SJohn Forte 	page[3] = m & 0xff;
6249fcf3ce44SJohn Forte 
6250fcf3ce44SJohn Forte 	return (n);
6251fcf3ce44SJohn Forte }
6252fcf3ce44SJohn Forte 
6253fcf3ce44SJohn Forte void
stmf_scsilib_handle_report_tpgs(scsi_task_t * task,stmf_data_buf_t * dbuf)6254fcf3ce44SJohn Forte stmf_scsilib_handle_report_tpgs(scsi_task_t *task, stmf_data_buf_t *dbuf)
6255fcf3ce44SJohn Forte {
6256fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
6257fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
625845039663SJohn Forte 	stmf_i_lu_t *ilu =
625945039663SJohn Forte 	    (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
6260fcf3ce44SJohn Forte 	stmf_xfer_data_t *xd;
6261fcf3ce44SJohn Forte 	uint32_t sz, minsz;
6262fcf3ce44SJohn Forte 
626361dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
6264fcf3ce44SJohn Forte 	itask->itask_flags |= ITASK_DEFAULT_HANDLING;
626561dfa509SRick McNeal 
6266fcf3ce44SJohn Forte 	task->task_cmd_xfer_length =
6267fcf3ce44SJohn Forte 	    ((((uint32_t)task->task_cdb[6]) << 24) |
6268fcf3ce44SJohn Forte 	    (((uint32_t)task->task_cdb[7]) << 16) |
6269fcf3ce44SJohn Forte 	    (((uint32_t)task->task_cdb[8]) << 8) |
6270fcf3ce44SJohn Forte 	    ((uint32_t)task->task_cdb[9]));
6271fcf3ce44SJohn Forte 
6272fcf3ce44SJohn Forte 	if (task->task_additional_flags &
6273fcf3ce44SJohn Forte 	    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
6274fcf3ce44SJohn Forte 		task->task_expected_xfer_length =
6275fcf3ce44SJohn Forte 		    task->task_cmd_xfer_length;
6276fcf3ce44SJohn Forte 	}
627761dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
6278fcf3ce44SJohn Forte 
6279729dd25cSWayne Ihde 	if (task->task_cmd_xfer_length == 0) {
6280729dd25cSWayne Ihde 		stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6281729dd25cSWayne Ihde 		return;
6282729dd25cSWayne Ihde 	}
6283729dd25cSWayne Ihde 	if (task->task_cmd_xfer_length < 4) {
6284fcf3ce44SJohn Forte 		stmf_scsilib_send_status(task, STATUS_CHECK,
6285fcf3ce44SJohn Forte 		    STMF_SAA_INVALID_FIELD_IN_CDB);
6286fcf3ce44SJohn Forte 		return;
6287fcf3ce44SJohn Forte 	}
6288fcf3ce44SJohn Forte 
6289fcf3ce44SJohn Forte 	sz = min(task->task_expected_xfer_length,
6290fcf3ce44SJohn Forte 	    task->task_cmd_xfer_length);
6291fcf3ce44SJohn Forte 
629245039663SJohn Forte 	xd = stmf_prepare_tpgs_data(ilu->ilu_alua);
6293fcf3ce44SJohn Forte 
6294fcf3ce44SJohn Forte 	if (xd == NULL) {
6295fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6296fcf3ce44SJohn Forte 		    STMF_ALLOC_FAILURE, NULL);
6297fcf3ce44SJohn Forte 		return;
6298fcf3ce44SJohn Forte 	}
6299fcf3ce44SJohn Forte 
6300fcf3ce44SJohn Forte 	sz = min(sz, xd->size_left);
6301fcf3ce44SJohn Forte 	xd->size_left = sz;
6302fcf3ce44SJohn Forte 	minsz = min(512, sz);
6303fcf3ce44SJohn Forte 
6304fcf3ce44SJohn Forte 	if (dbuf == NULL)
6305fcf3ce44SJohn Forte 		dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0);
6306fcf3ce44SJohn Forte 	if (dbuf == NULL) {
6307fcf3ce44SJohn Forte 		kmem_free(xd, xd->alloc_size);
6308fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6309fcf3ce44SJohn Forte 		    STMF_ALLOC_FAILURE, NULL);
6310fcf3ce44SJohn Forte 		return;
6311fcf3ce44SJohn Forte 	}
6312fcf3ce44SJohn Forte 	dbuf->db_lu_private = xd;
631391159e90SJohn Forte 	stmf_xd_to_dbuf(dbuf, 1);
6314fcf3ce44SJohn Forte 
6315fcf3ce44SJohn Forte 	dbuf->db_flags = DB_DIRECTION_TO_RPORT;
6316fcf3ce44SJohn Forte 	(void) stmf_xfer_data(task, dbuf, 0);
6317fcf3ce44SJohn Forte 
6318fcf3ce44SJohn Forte }
6319fcf3ce44SJohn Forte 
6320fcf3ce44SJohn Forte void
stmf_scsilib_handle_task_mgmt(scsi_task_t * task)6321fcf3ce44SJohn Forte stmf_scsilib_handle_task_mgmt(scsi_task_t *task)
6322fcf3ce44SJohn Forte {
632345039663SJohn Forte 
6324fcf3ce44SJohn Forte 	switch (task->task_mgmt_function) {
6325fcf3ce44SJohn Forte 	/*
6326fcf3ce44SJohn Forte 	 * For now we will abort all I/Os on the LU in case of ABORT_TASK_SET
6327fcf3ce44SJohn Forte 	 * and ABORT_TASK. But unlike LUN_RESET we will not reset LU state
6328fcf3ce44SJohn Forte 	 * in these cases. This needs to be changed to abort only the required
6329fcf3ce44SJohn Forte 	 * set.
6330fcf3ce44SJohn Forte 	 */
6331fcf3ce44SJohn Forte 	case TM_ABORT_TASK:
6332fcf3ce44SJohn Forte 	case TM_ABORT_TASK_SET:
6333fcf3ce44SJohn Forte 	case TM_CLEAR_TASK_SET:
6334fcf3ce44SJohn Forte 	case TM_LUN_RESET:
6335fcf3ce44SJohn Forte 		stmf_handle_lun_reset(task);
633645039663SJohn Forte 		/* issue the reset to the proxy node as well */
63377beff157SJohn Forte 		if (stmf_state.stmf_alua_state == 1) {
633845039663SJohn Forte 			(void) stmf_proxy_scsi_cmd(task, NULL);
63397beff157SJohn Forte 		}
6340fcf3ce44SJohn Forte 		return;
6341fcf3ce44SJohn Forte 	case TM_TARGET_RESET:
6342fcf3ce44SJohn Forte 	case TM_TARGET_COLD_RESET:
6343fcf3ce44SJohn Forte 	case TM_TARGET_WARM_RESET:
6344fcf3ce44SJohn Forte 		stmf_handle_target_reset(task);
6345fcf3ce44SJohn Forte 		return;
6346fcf3ce44SJohn Forte 	default:
6347fcf3ce44SJohn Forte 		/* We dont support this task mgmt function */
6348fcf3ce44SJohn Forte 		stmf_scsilib_send_status(task, STATUS_CHECK,
6349fcf3ce44SJohn Forte 		    STMF_SAA_INVALID_FIELD_IN_CMD_IU);
6350fcf3ce44SJohn Forte 		return;
6351fcf3ce44SJohn Forte 	}
6352fcf3ce44SJohn Forte }
6353fcf3ce44SJohn Forte 
6354fcf3ce44SJohn Forte void
stmf_handle_lun_reset(scsi_task_t * task)6355fcf3ce44SJohn Forte stmf_handle_lun_reset(scsi_task_t *task)
6356fcf3ce44SJohn Forte {
6357fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask;
6358fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
6359fcf3ce44SJohn Forte 
6360fcf3ce44SJohn Forte 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
6361fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
6362fcf3ce44SJohn Forte 
6363fcf3ce44SJohn Forte 	/*
6364fcf3ce44SJohn Forte 	 * To sync with target reset, grab this lock. The LU is not going
6365fcf3ce44SJohn Forte 	 * anywhere as there is atleast one task pending (this task).
6366fcf3ce44SJohn Forte 	 */
6367fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
6368fcf3ce44SJohn Forte 
6369fcf3ce44SJohn Forte 	if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
6370fcf3ce44SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
6371fcf3ce44SJohn Forte 		stmf_scsilib_send_status(task, STATUS_CHECK,
6372fcf3ce44SJohn Forte 		    STMF_SAA_OPERATION_IN_PROGRESS);
6373fcf3ce44SJohn Forte 		return;
6374fcf3ce44SJohn Forte 	}
6375fcf3ce44SJohn Forte 	atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE);
6376fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
6377fcf3ce44SJohn Forte 
6378fcf3ce44SJohn Forte 	/*
6379fcf3ce44SJohn Forte 	 * Mark this task as the one causing LU reset so that we know who
6380fcf3ce44SJohn Forte 	 * was responsible for setting the ILU_RESET_ACTIVE. In case this
6381fcf3ce44SJohn Forte 	 * task itself gets aborted, we will clear ILU_RESET_ACTIVE.
6382fcf3ce44SJohn Forte 	 */
638361dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
6384fcf3ce44SJohn Forte 	itask->itask_flags |= ITASK_DEFAULT_HANDLING | ITASK_CAUSING_LU_RESET;
638561dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
6386fcf3ce44SJohn Forte 
6387fcf3ce44SJohn Forte 	/* Initiatiate abort on all commands on this LU except this one */
6388fcf3ce44SJohn Forte 	stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED, task->task_lu);
6389fcf3ce44SJohn Forte 
6390fcf3ce44SJohn Forte 	/* Start polling on this task */
6391fcf3ce44SJohn Forte 	if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
6392fcf3ce44SJohn Forte 	    != STMF_SUCCESS) {
6393fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE,
6394fcf3ce44SJohn Forte 		    NULL);
6395fcf3ce44SJohn Forte 		return;
6396fcf3ce44SJohn Forte 	}
6397fcf3ce44SJohn Forte }
6398fcf3ce44SJohn Forte 
6399fcf3ce44SJohn Forte void
stmf_handle_target_reset(scsi_task_t * task)6400fcf3ce44SJohn Forte stmf_handle_target_reset(scsi_task_t *task)
6401fcf3ce44SJohn Forte {
6402fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask;
6403fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
6404fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
6405fcf3ce44SJohn Forte 	stmf_lun_map_t *lm;
6406fcf3ce44SJohn Forte 	stmf_lun_map_ent_t *lm_ent;
6407fcf3ce44SJohn Forte 	int i, lf;
6408fcf3ce44SJohn Forte 
6409fcf3ce44SJohn Forte 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
6410fcf3ce44SJohn Forte 	iss = (stmf_i_scsi_session_t *)task->task_session->ss_stmf_private;
6411fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
6412fcf3ce44SJohn Forte 
6413fcf3ce44SJohn Forte 	/*
6414fcf3ce44SJohn Forte 	 * To sync with LUN reset, grab this lock. The session is not going
6415fcf3ce44SJohn Forte 	 * anywhere as there is atleast one task pending (this task).
6416fcf3ce44SJohn Forte 	 */
6417fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
6418d6b3018dSSumit Gupta 
6419d6b3018dSSumit Gupta 	/* Grab the session lock as a writer to prevent any changes in it */
6420d6b3018dSSumit Gupta 	rw_enter(iss->iss_lockp, RW_WRITER);
6421d6b3018dSSumit Gupta 
6422fcf3ce44SJohn Forte 	if (iss->iss_flags & ISS_RESET_ACTIVE) {
6423fcf3ce44SJohn Forte 		rw_exit(iss->iss_lockp);
6424d6b3018dSSumit Gupta 		mutex_exit(&stmf_state.stmf_lock);
6425fcf3ce44SJohn Forte 		stmf_scsilib_send_status(task, STATUS_CHECK,
6426fcf3ce44SJohn Forte 		    STMF_SAA_OPERATION_IN_PROGRESS);
6427fcf3ce44SJohn Forte 		return;
6428fcf3ce44SJohn Forte 	}
6429fcf3ce44SJohn Forte 	atomic_or_32(&iss->iss_flags, ISS_RESET_ACTIVE);
6430fcf3ce44SJohn Forte 
6431fcf3ce44SJohn Forte 	/*
6432fcf3ce44SJohn Forte 	 * Now go through each LUN in this session and make sure all of them
6433fcf3ce44SJohn Forte 	 * can be reset.
6434fcf3ce44SJohn Forte 	 */
6435fcf3ce44SJohn Forte 	lm = iss->iss_sm;
6436fcf3ce44SJohn Forte 	for (i = 0, lf = 0; i < lm->lm_nentries; i++) {
6437fcf3ce44SJohn Forte 		if (lm->lm_plus[i] == NULL)
6438fcf3ce44SJohn Forte 			continue;
6439fcf3ce44SJohn Forte 		lf++;
6440fcf3ce44SJohn Forte 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6441fcf3ce44SJohn Forte 		ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private);
6442fcf3ce44SJohn Forte 		if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
6443fcf3ce44SJohn Forte 			atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
6444fcf3ce44SJohn Forte 			rw_exit(iss->iss_lockp);
6445d6b3018dSSumit Gupta 			mutex_exit(&stmf_state.stmf_lock);
6446fcf3ce44SJohn Forte 			stmf_scsilib_send_status(task, STATUS_CHECK,
6447fcf3ce44SJohn Forte 			    STMF_SAA_OPERATION_IN_PROGRESS);
6448fcf3ce44SJohn Forte 			return;
6449fcf3ce44SJohn Forte 		}
6450fcf3ce44SJohn Forte 	}
6451fcf3ce44SJohn Forte 	if (lf == 0) {
6452fcf3ce44SJohn Forte 		/* No luns in this session */
6453fcf3ce44SJohn Forte 		atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
6454fcf3ce44SJohn Forte 		rw_exit(iss->iss_lockp);
6455d6b3018dSSumit Gupta 		mutex_exit(&stmf_state.stmf_lock);
6456fcf3ce44SJohn Forte 		stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6457fcf3ce44SJohn Forte 		return;
6458fcf3ce44SJohn Forte 	}
6459fcf3ce44SJohn Forte 
6460fcf3ce44SJohn Forte 	/* ok, start the damage */
646161dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
6462fcf3ce44SJohn Forte 	itask->itask_flags |= ITASK_DEFAULT_HANDLING |
6463fcf3ce44SJohn Forte 	    ITASK_CAUSING_TARGET_RESET;
646461dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
6465fcf3ce44SJohn Forte 	for (i = 0; i < lm->lm_nentries; i++) {
6466fcf3ce44SJohn Forte 		if (lm->lm_plus[i] == NULL)
6467fcf3ce44SJohn Forte 			continue;
6468fcf3ce44SJohn Forte 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6469fcf3ce44SJohn Forte 		ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private);
6470fcf3ce44SJohn Forte 		atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE);
6471fcf3ce44SJohn Forte 	}
6472fcf3ce44SJohn Forte 
6473fcf3ce44SJohn Forte 	for (i = 0; i < lm->lm_nentries; i++) {
6474fcf3ce44SJohn Forte 		if (lm->lm_plus[i] == NULL)
6475fcf3ce44SJohn Forte 			continue;
6476fcf3ce44SJohn Forte 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6477fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED,
6478fcf3ce44SJohn Forte 		    lm_ent->ent_lu);
6479fcf3ce44SJohn Forte 	}
6480fcf3ce44SJohn Forte 
6481780c822cStim szeto 	rw_exit(iss->iss_lockp);
6482780c822cStim szeto 	mutex_exit(&stmf_state.stmf_lock);
6483780c822cStim szeto 
6484fcf3ce44SJohn Forte 	/* Start polling on this task */
6485fcf3ce44SJohn Forte 	if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
6486fcf3ce44SJohn Forte 	    != STMF_SUCCESS) {
6487fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE,
6488fcf3ce44SJohn Forte 		    NULL);
6489fcf3ce44SJohn Forte 		return;
6490fcf3ce44SJohn Forte 	}
6491fcf3ce44SJohn Forte }
6492fcf3ce44SJohn Forte 
6493fcf3ce44SJohn Forte int
stmf_handle_cmd_during_ic(stmf_i_scsi_task_t * itask)6494fcf3ce44SJohn Forte stmf_handle_cmd_during_ic(stmf_i_scsi_task_t *itask)
6495fcf3ce44SJohn Forte {
6496fcf3ce44SJohn Forte 	scsi_task_t *task = itask->itask_task;
6497fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
6498fcf3ce44SJohn Forte 	    task->task_session->ss_stmf_private;
6499fcf3ce44SJohn Forte 
6500fcf3ce44SJohn Forte 	rw_enter(iss->iss_lockp, RW_WRITER);
6501fcf3ce44SJohn Forte 	if (((iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) == 0) ||
6502fcf3ce44SJohn Forte 	    (task->task_cdb[0] == SCMD_INQUIRY)) {
6503fcf3ce44SJohn Forte 		rw_exit(iss->iss_lockp);
6504fcf3ce44SJohn Forte 		return (0);
6505fcf3ce44SJohn Forte 	}
6506fcf3ce44SJohn Forte 	atomic_and_32(&iss->iss_flags,
6507fcf3ce44SJohn Forte 	    ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS));
6508fcf3ce44SJohn Forte 	rw_exit(iss->iss_lockp);
6509fcf3ce44SJohn Forte 
6510fcf3ce44SJohn Forte 	if (task->task_cdb[0] == SCMD_REPORT_LUNS) {
6511fcf3ce44SJohn Forte 		return (0);
6512fcf3ce44SJohn Forte 	}
6513fcf3ce44SJohn Forte 	stmf_scsilib_send_status(task, STATUS_CHECK,
6514fcf3ce44SJohn Forte 	    STMF_SAA_REPORT_LUN_DATA_HAS_CHANGED);
6515fcf3ce44SJohn Forte 	return (1);
6516fcf3ce44SJohn Forte }
6517fcf3ce44SJohn Forte 
6518fcf3ce44SJohn Forte void
stmf_worker_init()6519fcf3ce44SJohn Forte stmf_worker_init()
6520fcf3ce44SJohn Forte {
6521fcf3ce44SJohn Forte 	uint32_t i;
652261dfa509SRick McNeal 	stmf_worker_t *w;
6523fcf3ce44SJohn Forte 
6524fcf3ce44SJohn Forte 	/* Make local copy of global tunables */
6525fcf3ce44SJohn Forte 
652661dfa509SRick McNeal 	/*
652761dfa509SRick McNeal 	 * Allow workers to be scaled down to a very low number for cases
652861dfa509SRick McNeal 	 * where the load is light.  If the number of threads gets below
652961dfa509SRick McNeal 	 * 4 assume it is a mistake and force the threads back to a
653061dfa509SRick McNeal 	 * reasonable number.  The low limit of 4 is simply legacy and
653161dfa509SRick McNeal 	 * may be too low.
653261dfa509SRick McNeal 	 */
6533fcf3ce44SJohn Forte 	ASSERT(stmf_workers == NULL);
653461dfa509SRick McNeal 	if (stmf_nworkers < 4) {
653561dfa509SRick McNeal 		stmf_nworkers = 64;
6536fcf3ce44SJohn Forte 	}
653761dfa509SRick McNeal 
6538fcf3ce44SJohn Forte 	stmf_workers = (stmf_worker_t *)kmem_zalloc(
653961dfa509SRick McNeal 	    sizeof (stmf_worker_t) * stmf_nworkers, KM_SLEEP);
654061dfa509SRick McNeal 	for (i = 0; i < stmf_nworkers; i++) {
6541fcf3ce44SJohn Forte 		stmf_worker_t *w = &stmf_workers[i];
6542fcf3ce44SJohn Forte 		mutex_init(&w->worker_lock, NULL, MUTEX_DRIVER, NULL);
6543fcf3ce44SJohn Forte 		cv_init(&w->worker_cv, NULL, CV_DRIVER, NULL);
6544fcf3ce44SJohn Forte 	}
6545fcf3ce44SJohn Forte 	stmf_workers_state = STMF_WORKERS_ENABLED;
6546fcf3ce44SJohn Forte 
654761dfa509SRick McNeal 	/* Check if we are starting */
654861dfa509SRick McNeal 	if (stmf_nworkers_cur < stmf_nworkers - 1) {
654961dfa509SRick McNeal 		for (i = stmf_nworkers_cur; i < stmf_nworkers; i++) {
655061dfa509SRick McNeal 			w = &stmf_workers[i];
655161dfa509SRick McNeal 			w->worker_tid = thread_create(NULL, 0, stmf_worker_task,
655261dfa509SRick McNeal 			    (void *)&stmf_workers[i], 0, &p0, TS_RUN,
655361dfa509SRick McNeal 			    minclsyspri);
655461dfa509SRick McNeal 			stmf_nworkers_accepting_cmds++;
655561dfa509SRick McNeal 		}
655661dfa509SRick McNeal 		return;
655761dfa509SRick McNeal 	}
6558fcf3ce44SJohn Forte 
6559fcf3ce44SJohn Forte 	/* Lets wait for atleast one worker to start */
6560fcf3ce44SJohn Forte 	while (stmf_nworkers_cur == 0)
6561fcf3ce44SJohn Forte 		delay(drv_usectohz(20 * 1000));
6562fcf3ce44SJohn Forte }
6563fcf3ce44SJohn Forte 
6564fcf3ce44SJohn Forte stmf_status_t
stmf_worker_fini()6565fcf3ce44SJohn Forte stmf_worker_fini()
6566fcf3ce44SJohn Forte {
6567fcf3ce44SJohn Forte 	int i;
6568fcf3ce44SJohn Forte 	clock_t sb;
6569fcf3ce44SJohn Forte 
6570fcf3ce44SJohn Forte 	if (stmf_workers_state == STMF_WORKERS_DISABLED)
6571fcf3ce44SJohn Forte 		return (STMF_SUCCESS);
6572fcf3ce44SJohn Forte 	ASSERT(stmf_workers);
6573fcf3ce44SJohn Forte 	stmf_workers_state = STMF_WORKERS_DISABLED;
6574fcf3ce44SJohn Forte 	cv_signal(&stmf_state.stmf_cv);
6575fcf3ce44SJohn Forte 
6576fcf3ce44SJohn Forte 	sb = ddi_get_lbolt() + drv_usectohz(10 * 1000 * 1000);
6577fcf3ce44SJohn Forte 	/* Wait for all the threads to die */
6578fcf3ce44SJohn Forte 	while (stmf_nworkers_cur != 0) {
6579fcf3ce44SJohn Forte 		if (ddi_get_lbolt() > sb) {
6580fcf3ce44SJohn Forte 			stmf_workers_state = STMF_WORKERS_ENABLED;
6581fcf3ce44SJohn Forte 			return (STMF_BUSY);
6582fcf3ce44SJohn Forte 		}
6583fcf3ce44SJohn Forte 		delay(drv_usectohz(100 * 1000));
6584fcf3ce44SJohn Forte 	}
658561dfa509SRick McNeal 	for (i = 0; i < stmf_nworkers; i++) {
6586fcf3ce44SJohn Forte 		stmf_worker_t *w = &stmf_workers[i];
6587fcf3ce44SJohn Forte 		mutex_destroy(&w->worker_lock);
6588fcf3ce44SJohn Forte 		cv_destroy(&w->worker_cv);
6589fcf3ce44SJohn Forte 	}
659061dfa509SRick McNeal 	kmem_free(stmf_workers, sizeof (stmf_worker_t) * stmf_nworkers);
6591fcf3ce44SJohn Forte 	stmf_workers = NULL;
6592fcf3ce44SJohn Forte 
6593fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
6594fcf3ce44SJohn Forte }
6595fcf3ce44SJohn Forte 
6596fcf3ce44SJohn Forte void
stmf_worker_task(void * arg)6597fcf3ce44SJohn Forte stmf_worker_task(void *arg)
6598fcf3ce44SJohn Forte {
6599fcf3ce44SJohn Forte 	stmf_worker_t *w;
6600fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
6601fcf3ce44SJohn Forte 	scsi_task_t *task;
6602fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask;
6603fcf3ce44SJohn Forte 	stmf_data_buf_t *dbuf;
6604fcf3ce44SJohn Forte 	stmf_lu_t *lu;
6605fcf3ce44SJohn Forte 	clock_t wait_timer = 0;
6606d3d50737SRafael Vanoni 	clock_t wait_ticks, wait_delta = 0;
6607fcf3ce44SJohn Forte 	uint8_t curcmd;
6608fcf3ce44SJohn Forte 	uint8_t abort_free;
6609fcf3ce44SJohn Forte 	uint8_t wait_queue;
6610fcf3ce44SJohn Forte 	uint8_t dec_qdepth;
6611fcf3ce44SJohn Forte 
6612fcf3ce44SJohn Forte 	w = (stmf_worker_t *)arg;
6613fcf3ce44SJohn Forte 	wait_ticks = drv_usectohz(10000);
6614fcf3ce44SJohn Forte 
6615427fcaf8Stim szeto 	DTRACE_PROBE1(worker__create, stmf_worker_t, w);
6616fcf3ce44SJohn Forte 	mutex_enter(&w->worker_lock);
6617fcf3ce44SJohn Forte 	w->worker_flags |= STMF_WORKER_STARTED | STMF_WORKER_ACTIVE;
661861dfa509SRick McNeal 	atomic_inc_32(&stmf_nworkers_cur);
661961dfa509SRick McNeal 
662061dfa509SRick McNeal stmf_worker_loop:
6621fcf3ce44SJohn Forte 	if ((w->worker_ref_count == 0) &&
6622fcf3ce44SJohn Forte 	    (w->worker_flags & STMF_WORKER_TERMINATE)) {
6623fcf3ce44SJohn Forte 		w->worker_flags &= ~(STMF_WORKER_STARTED |
6624fcf3ce44SJohn Forte 		    STMF_WORKER_ACTIVE | STMF_WORKER_TERMINATE);
6625fcf3ce44SJohn Forte 		w->worker_tid = NULL;
6626fcf3ce44SJohn Forte 		mutex_exit(&w->worker_lock);
6627427fcaf8Stim szeto 		DTRACE_PROBE1(worker__destroy, stmf_worker_t, w);
662861dfa509SRick McNeal 		atomic_dec_32(&stmf_nworkers_cur);
6629fcf3ce44SJohn Forte 		thread_exit();
6630fcf3ce44SJohn Forte 	}
663161dfa509SRick McNeal 
6632fcf3ce44SJohn Forte 	/* CONSTCOND */
6633fcf3ce44SJohn Forte 	while (1) {
663461dfa509SRick McNeal 		/* worker lock is held at this point */
6635fcf3ce44SJohn Forte 		dec_qdepth = 0;
6636fcf3ce44SJohn Forte 		if (wait_timer && (ddi_get_lbolt() >= wait_timer)) {
6637fcf3ce44SJohn Forte 			wait_timer = 0;
6638d3d50737SRafael Vanoni 			wait_delta = 0;
6639d6b3018dSSumit Gupta 			if (w->worker_wait_head) {
6640d6b3018dSSumit Gupta 				ASSERT(w->worker_wait_tail);
6641fcf3ce44SJohn Forte 				if (w->worker_task_head == NULL)
6642d6b3018dSSumit Gupta 					w->worker_task_head =
6643d6b3018dSSumit Gupta 					    w->worker_wait_head;
6644fcf3ce44SJohn Forte 				else
6645fcf3ce44SJohn Forte 					w->worker_task_tail->itask_worker_next =
6646fcf3ce44SJohn Forte 					    w->worker_wait_head;
6647fcf3ce44SJohn Forte 				w->worker_task_tail = w->worker_wait_tail;
6648d6b3018dSSumit Gupta 				w->worker_wait_head = w->worker_wait_tail =
6649d6b3018dSSumit Gupta 				    NULL;
6650d6b3018dSSumit Gupta 			}
6651fcf3ce44SJohn Forte 		}
665261dfa509SRick McNeal 
665361dfa509SRick McNeal 		STMF_DEQUEUE_ITASK(w, itask);
665461dfa509SRick McNeal 		if (itask == NULL)
6655fcf3ce44SJohn Forte 			break;
665661dfa509SRick McNeal 
665761dfa509SRick McNeal 		ASSERT((itask->itask_flags & ITASK_IN_FREE_LIST) == 0);
6658fcf3ce44SJohn Forte 		task = itask->itask_task;
6659427fcaf8Stim szeto 		DTRACE_PROBE2(worker__active, stmf_worker_t, w,
6660427fcaf8Stim szeto 		    scsi_task_t *, task);
6661fcf3ce44SJohn Forte 		wait_queue = 0;
6662fcf3ce44SJohn Forte 		abort_free = 0;
666361dfa509SRick McNeal 		mutex_exit(&w->worker_lock);
666461dfa509SRick McNeal 		mutex_enter(&itask->itask_mutex);
666561dfa509SRick McNeal 		mutex_enter(&w->worker_lock);
666661dfa509SRick McNeal 
6667fcf3ce44SJohn Forte 		if (itask->itask_ncmds > 0) {
6668fcf3ce44SJohn Forte 			curcmd = itask->itask_cmd_stack[itask->itask_ncmds - 1];
6669fcf3ce44SJohn Forte 		} else {
6670fcf3ce44SJohn Forte 			ASSERT(itask->itask_flags & ITASK_BEING_ABORTED);
6671fcf3ce44SJohn Forte 		}
667261dfa509SRick McNeal 		if (itask->itask_flags & ITASK_BEING_ABORTED) {
6673fcf3ce44SJohn Forte 			itask->itask_ncmds = 1;
6674fcf3ce44SJohn Forte 			curcmd = itask->itask_cmd_stack[0] =
6675fcf3ce44SJohn Forte 			    ITASK_CMD_ABORT;
6676fcf3ce44SJohn Forte 			goto out_itask_flag_loop;
667761dfa509SRick McNeal 		} else if ((curcmd & ITASK_CMD_MASK) == ITASK_CMD_NEW_TASK) {
6678554c2b16Stim szeto 			/*
6679554c2b16Stim szeto 			 * set ITASK_KSTAT_IN_RUNQ, this flag
6680554c2b16Stim szeto 			 * will not reset until task completed
6681554c2b16Stim szeto 			 */
668261dfa509SRick McNeal 			itask->itask_flags |= ITASK_KNOWN_TO_LU |
6683554c2b16Stim szeto 			    ITASK_KSTAT_IN_RUNQ;
6684fcf3ce44SJohn Forte 		} else {
6685fcf3ce44SJohn Forte 			goto out_itask_flag_loop;
6686fcf3ce44SJohn Forte 		}
6687fcf3ce44SJohn Forte 
6688fcf3ce44SJohn Forte out_itask_flag_loop:
6689fcf3ce44SJohn Forte 
6690fcf3ce44SJohn Forte 		/*
6691fcf3ce44SJohn Forte 		 * Decide if this task needs to go to a queue and/or if
6692fcf3ce44SJohn Forte 		 * we can decrement the itask_cmd_stack.
6693fcf3ce44SJohn Forte 		 */
6694fcf3ce44SJohn Forte 		if (curcmd == ITASK_CMD_ABORT) {
6695fcf3ce44SJohn Forte 			if (itask->itask_flags & (ITASK_KNOWN_TO_LU |
6696fcf3ce44SJohn Forte 			    ITASK_KNOWN_TO_TGT_PORT)) {
6697fcf3ce44SJohn Forte 				wait_queue = 1;
6698fcf3ce44SJohn Forte 			} else {
6699fcf3ce44SJohn Forte 				abort_free = 1;
6700fcf3ce44SJohn Forte 			}
6701fcf3ce44SJohn Forte 		} else if ((curcmd & ITASK_CMD_POLL) &&
6702fcf3ce44SJohn Forte 		    (itask->itask_poll_timeout > ddi_get_lbolt())) {
6703fcf3ce44SJohn Forte 			wait_queue = 1;
6704fcf3ce44SJohn Forte 		}
6705fcf3ce44SJohn Forte 
6706fcf3ce44SJohn Forte 		if (wait_queue) {
6707fcf3ce44SJohn Forte 			itask->itask_worker_next = NULL;
6708fcf3ce44SJohn Forte 			if (w->worker_wait_tail) {
6709fcf3ce44SJohn Forte 				w->worker_wait_tail->itask_worker_next = itask;
6710fcf3ce44SJohn Forte 			} else {
6711fcf3ce44SJohn Forte 				w->worker_wait_head = itask;
6712fcf3ce44SJohn Forte 			}
6713fcf3ce44SJohn Forte 			w->worker_wait_tail = itask;
6714fcf3ce44SJohn Forte 			if (wait_timer == 0) {
6715fcf3ce44SJohn Forte 				wait_timer = ddi_get_lbolt() + wait_ticks;
6716d3d50737SRafael Vanoni 				wait_delta = wait_ticks;
6717fcf3ce44SJohn Forte 			}
6718fcf3ce44SJohn Forte 		} else if ((--(itask->itask_ncmds)) != 0) {
6719fcf3ce44SJohn Forte 			itask->itask_worker_next = NULL;
6720fcf3ce44SJohn Forte 			if (w->worker_task_tail) {
6721fcf3ce44SJohn Forte 				w->worker_task_tail->itask_worker_next = itask;
6722fcf3ce44SJohn Forte 			} else {
6723fcf3ce44SJohn Forte 				w->worker_task_head = itask;
6724fcf3ce44SJohn Forte 			}
6725fcf3ce44SJohn Forte 			w->worker_task_tail = itask;
6726fcf3ce44SJohn Forte 		} else {
6727fcf3ce44SJohn Forte 			atomic_and_32(&itask->itask_flags,
6728fcf3ce44SJohn Forte 			    ~ITASK_IN_WORKER_QUEUE);
6729fcf3ce44SJohn Forte 			/*
6730fcf3ce44SJohn Forte 			 * This is where the queue depth should go down by
6731fcf3ce44SJohn Forte 			 * one but we delay that on purpose to account for
6732fcf3ce44SJohn Forte 			 * the call into the provider. The actual decrement
6733fcf3ce44SJohn Forte 			 * happens after the worker has done its job.
6734fcf3ce44SJohn Forte 			 */
6735fcf3ce44SJohn Forte 			dec_qdepth = 1;
6736427fcaf8Stim szeto 			itask->itask_waitq_time +=
6737427fcaf8Stim szeto 			    gethrtime() - itask->itask_waitq_enter_timestamp;
6738fcf3ce44SJohn Forte 		}
6739fcf3ce44SJohn Forte 
6740fcf3ce44SJohn Forte 		/* We made it here means we are going to call LU */
6741fcf3ce44SJohn Forte 		if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0)
6742fcf3ce44SJohn Forte 			lu = task->task_lu;
6743fcf3ce44SJohn Forte 		else
6744fcf3ce44SJohn Forte 			lu = dlun0;
674561dfa509SRick McNeal 
6746fcf3ce44SJohn Forte 		dbuf = itask->itask_dbufs[ITASK_CMD_BUF_NDX(curcmd)];
6747fcf3ce44SJohn Forte 		mutex_exit(&w->worker_lock);
6748fcf3ce44SJohn Forte 		curcmd &= ITASK_CMD_MASK;
674940c3e8ffSJohn Forte 		stmf_task_audit(itask, TE_PROCESS_CMD, curcmd, dbuf);
675061dfa509SRick McNeal 		mutex_exit(&itask->itask_mutex);
675161dfa509SRick McNeal 
6752fcf3ce44SJohn Forte 		switch (curcmd) {
6753fcf3ce44SJohn Forte 		case ITASK_CMD_NEW_TASK:
6754fcf3ce44SJohn Forte 			iss = (stmf_i_scsi_session_t *)
6755fcf3ce44SJohn Forte 			    task->task_session->ss_stmf_private;
6756427fcaf8Stim szeto 			stmf_itl_lu_new_task(itask);
6757fcf3ce44SJohn Forte 			if (iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) {
675861dfa509SRick McNeal 				if (stmf_handle_cmd_during_ic(itask)) {
6759fcf3ce44SJohn Forte 					break;
6760fcf3ce44SJohn Forte 				}
676161dfa509SRick McNeal 			}
6762fcf3ce44SJohn Forte #ifdef	DEBUG
6763fcf3ce44SJohn Forte 			if (stmf_drop_task_counter > 0) {
676461dfa509SRick McNeal 				if (atomic_dec_32_nv(
676561dfa509SRick McNeal 				    (uint32_t *)&stmf_drop_task_counter) == 1) {
6766fcf3ce44SJohn Forte 					break;
6767fcf3ce44SJohn Forte 				}
676861dfa509SRick McNeal 			}
6769fcf3ce44SJohn Forte #endif
6770e17f3b22Stim szeto 			DTRACE_PROBE1(scsi__task__start, scsi_task_t *, task);
6771fcf3ce44SJohn Forte 			lu->lu_new_task(task, dbuf);
6772fcf3ce44SJohn Forte 			break;
6773fcf3ce44SJohn Forte 		case ITASK_CMD_DATA_XFER_DONE:
6774fcf3ce44SJohn Forte 			lu->lu_dbuf_xfer_done(task, dbuf);
6775fcf3ce44SJohn Forte 			break;
6776fcf3ce44SJohn Forte 		case ITASK_CMD_STATUS_DONE:
6777fcf3ce44SJohn Forte 			lu->lu_send_status_done(task);
6778fcf3ce44SJohn Forte 			break;
6779fcf3ce44SJohn Forte 		case ITASK_CMD_ABORT:
6780fcf3ce44SJohn Forte 			if (abort_free) {
678161dfa509SRick McNeal 				mutex_enter(&itask->itask_mutex);
6782fcf3ce44SJohn Forte 				stmf_task_free(task);
6783fcf3ce44SJohn Forte 			} else {
6784fcf3ce44SJohn Forte 				stmf_do_task_abort(task);
6785fcf3ce44SJohn Forte 			}
6786fcf3ce44SJohn Forte 			break;
6787fcf3ce44SJohn Forte 		case ITASK_CMD_POLL_LU:
6788fcf3ce44SJohn Forte 			if (!wait_queue) {
6789fcf3ce44SJohn Forte 				lu->lu_task_poll(task);
6790fcf3ce44SJohn Forte 			}
6791fcf3ce44SJohn Forte 			break;
6792fcf3ce44SJohn Forte 		case ITASK_CMD_POLL_LPORT:
6793fcf3ce44SJohn Forte 			if (!wait_queue)
6794fcf3ce44SJohn Forte 				task->task_lport->lport_task_poll(task);
6795fcf3ce44SJohn Forte 			break;
6796fcf3ce44SJohn Forte 		case ITASK_CMD_SEND_STATUS:
6797fcf3ce44SJohn Forte 		/* case ITASK_CMD_XFER_DATA: */
6798fcf3ce44SJohn Forte 			break;
6799fcf3ce44SJohn Forte 		}
680061dfa509SRick McNeal 
6801fcf3ce44SJohn Forte 		mutex_enter(&w->worker_lock);
6802fcf3ce44SJohn Forte 		if (dec_qdepth) {
6803fcf3ce44SJohn Forte 			w->worker_queue_depth--;
6804fcf3ce44SJohn Forte 		}
6805fcf3ce44SJohn Forte 	}
6806fcf3ce44SJohn Forte 	if ((w->worker_flags & STMF_WORKER_TERMINATE) && (wait_timer == 0)) {
6807fcf3ce44SJohn Forte 		if (w->worker_ref_count == 0)
6808fcf3ce44SJohn Forte 			goto stmf_worker_loop;
6809d3d50737SRafael Vanoni 		else {
6810fcf3ce44SJohn Forte 			wait_timer = ddi_get_lbolt() + 1;
6811d3d50737SRafael Vanoni 			wait_delta = 1;
6812d3d50737SRafael Vanoni 		}
6813fcf3ce44SJohn Forte 	}
6814fcf3ce44SJohn Forte 	w->worker_flags &= ~STMF_WORKER_ACTIVE;
6815fcf3ce44SJohn Forte 	if (wait_timer) {
6816427fcaf8Stim szeto 		DTRACE_PROBE1(worker__timed__sleep, stmf_worker_t, w);
6817d3d50737SRafael Vanoni 		(void) cv_reltimedwait(&w->worker_cv, &w->worker_lock,
6818d3d50737SRafael Vanoni 		    wait_delta, TR_CLOCK_TICK);
6819fcf3ce44SJohn Forte 	} else {
6820427fcaf8Stim szeto 		DTRACE_PROBE1(worker__sleep, stmf_worker_t, w);
6821fcf3ce44SJohn Forte 		cv_wait(&w->worker_cv, &w->worker_lock);
6822fcf3ce44SJohn Forte 	}
6823427fcaf8Stim szeto 	DTRACE_PROBE1(worker__wakeup, stmf_worker_t, w);
6824fcf3ce44SJohn Forte 	w->worker_flags |= STMF_WORKER_ACTIVE;
6825fcf3ce44SJohn Forte 	goto stmf_worker_loop;
6826fcf3ce44SJohn Forte }
6827fcf3ce44SJohn Forte 
6828fcf3ce44SJohn Forte /*
6829fcf3ce44SJohn Forte  * Fills out a dbuf from stmf_xfer_data_t (contained in the db_lu_private).
6830fcf3ce44SJohn Forte  * If all the data has been filled out, frees the xd and makes
6831fcf3ce44SJohn Forte  * db_lu_private NULL.
6832fcf3ce44SJohn Forte  */
6833fcf3ce44SJohn Forte void
stmf_xd_to_dbuf(stmf_data_buf_t * dbuf,int set_rel_off)683491159e90SJohn Forte stmf_xd_to_dbuf(stmf_data_buf_t *dbuf, int set_rel_off)
6835fcf3ce44SJohn Forte {
6836fcf3ce44SJohn Forte 	stmf_xfer_data_t *xd;
6837fcf3ce44SJohn Forte 	uint8_t *p;
6838fcf3ce44SJohn Forte 	int i;
6839fcf3ce44SJohn Forte 	uint32_t s;
6840fcf3ce44SJohn Forte 
6841fcf3ce44SJohn Forte 	xd = (stmf_xfer_data_t *)dbuf->db_lu_private;
6842fcf3ce44SJohn Forte 	dbuf->db_data_size = 0;
684391159e90SJohn Forte 	if (set_rel_off)
6844fcf3ce44SJohn Forte 		dbuf->db_relative_offset = xd->size_done;
6845fcf3ce44SJohn Forte 	for (i = 0; i < dbuf->db_sglist_length; i++) {
6846fcf3ce44SJohn Forte 		s = min(xd->size_left, dbuf->db_sglist[i].seg_length);
6847fcf3ce44SJohn Forte 		p = &xd->buf[xd->size_done];
6848fcf3ce44SJohn Forte 		bcopy(p, dbuf->db_sglist[i].seg_addr, s);
6849fcf3ce44SJohn Forte 		xd->size_left -= s;
6850fcf3ce44SJohn Forte 		xd->size_done += s;
6851fcf3ce44SJohn Forte 		dbuf->db_data_size += s;
6852fcf3ce44SJohn Forte 		if (xd->size_left == 0) {
6853fcf3ce44SJohn Forte 			kmem_free(xd, xd->alloc_size);
6854fcf3ce44SJohn Forte 			dbuf->db_lu_private = NULL;
6855fcf3ce44SJohn Forte 			return;
6856fcf3ce44SJohn Forte 		}
6857fcf3ce44SJohn Forte 	}
6858fcf3ce44SJohn Forte }
6859fcf3ce44SJohn Forte 
6860fcf3ce44SJohn Forte /* ARGSUSED */
6861fcf3ce44SJohn Forte stmf_status_t
stmf_dlun0_task_alloc(scsi_task_t * task)6862fcf3ce44SJohn Forte stmf_dlun0_task_alloc(scsi_task_t *task)
6863fcf3ce44SJohn Forte {
6864fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
6865fcf3ce44SJohn Forte }
6866fcf3ce44SJohn Forte 
6867fcf3ce44SJohn Forte void
stmf_dlun0_new_task(scsi_task_t * task,stmf_data_buf_t * dbuf)6868fcf3ce44SJohn Forte stmf_dlun0_new_task(scsi_task_t *task, stmf_data_buf_t *dbuf)
6869fcf3ce44SJohn Forte {
6870fcf3ce44SJohn Forte 	uint8_t *cdbp = (uint8_t *)&task->task_cdb[0];
6871fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
6872fcf3ce44SJohn Forte 	uint32_t sz, minsz;
6873fcf3ce44SJohn Forte 	uint8_t *p;
6874fcf3ce44SJohn Forte 	stmf_xfer_data_t *xd;
6875fcf3ce44SJohn Forte 	uint8_t inq_page_length = 31;
6876fcf3ce44SJohn Forte 
6877fcf3ce44SJohn Forte 	if (task->task_mgmt_function) {
6878fcf3ce44SJohn Forte 		stmf_scsilib_handle_task_mgmt(task);
6879fcf3ce44SJohn Forte 		return;
6880fcf3ce44SJohn Forte 	}
6881fcf3ce44SJohn Forte 
6882fcf3ce44SJohn Forte 	switch (cdbp[0]) {
6883fcf3ce44SJohn Forte 	case SCMD_INQUIRY:
6884fcf3ce44SJohn Forte 		/*
6885fcf3ce44SJohn Forte 		 * Basic protocol checks.  In addition, only reply to
6886fcf3ce44SJohn Forte 		 * standard inquiry.  Otherwise, the LU provider needs
6887fcf3ce44SJohn Forte 		 * to respond.
6888fcf3ce44SJohn Forte 		 */
6889fcf3ce44SJohn Forte 
6890fcf3ce44SJohn Forte 		if (cdbp[2] || (cdbp[1] & 1) || cdbp[5]) {
6891fcf3ce44SJohn Forte 			stmf_scsilib_send_status(task, STATUS_CHECK,
6892fcf3ce44SJohn Forte 			    STMF_SAA_INVALID_FIELD_IN_CDB);
6893fcf3ce44SJohn Forte 			return;
6894fcf3ce44SJohn Forte 		}
6895fcf3ce44SJohn Forte 
6896fcf3ce44SJohn Forte 		task->task_cmd_xfer_length =
6897fcf3ce44SJohn Forte 		    (((uint32_t)cdbp[3]) << 8) | cdbp[4];
6898fcf3ce44SJohn Forte 
6899fcf3ce44SJohn Forte 		if (task->task_additional_flags &
6900fcf3ce44SJohn Forte 		    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
6901fcf3ce44SJohn Forte 			task->task_expected_xfer_length =
6902fcf3ce44SJohn Forte 			    task->task_cmd_xfer_length;
6903fcf3ce44SJohn Forte 		}
6904fcf3ce44SJohn Forte 
6905fcf3ce44SJohn Forte 		sz = min(task->task_expected_xfer_length,
6906fcf3ce44SJohn Forte 		    min(36, task->task_cmd_xfer_length));
6907fcf3ce44SJohn Forte 		minsz = 36;
6908fcf3ce44SJohn Forte 
6909fcf3ce44SJohn Forte 		if (sz == 0) {
6910fcf3ce44SJohn Forte 			stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6911fcf3ce44SJohn Forte 			return;
6912fcf3ce44SJohn Forte 		}
6913fcf3ce44SJohn Forte 
6914fcf3ce44SJohn Forte 		if (dbuf && (dbuf->db_sglist[0].seg_length < 36)) {
6915fcf3ce44SJohn Forte 			/*
6916fcf3ce44SJohn Forte 			 * Ignore any preallocated dbuf if the size is less
6917fcf3ce44SJohn Forte 			 * than 36. It will be freed during the task_free.
6918fcf3ce44SJohn Forte 			 */
6919fcf3ce44SJohn Forte 			dbuf = NULL;
6920fcf3ce44SJohn Forte 		}
6921fcf3ce44SJohn Forte 		if (dbuf == NULL)
6922fcf3ce44SJohn Forte 			dbuf = stmf_alloc_dbuf(task, minsz, &minsz, 0);
6923fcf3ce44SJohn Forte 		if ((dbuf == NULL) || (dbuf->db_sglist[0].seg_length < sz)) {
6924fcf3ce44SJohn Forte 			stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6925fcf3ce44SJohn Forte 			    STMF_ALLOC_FAILURE, NULL);
6926fcf3ce44SJohn Forte 			return;
6927fcf3ce44SJohn Forte 		}
6928fcf3ce44SJohn Forte 		dbuf->db_lu_private = NULL;
6929fcf3ce44SJohn Forte 
6930fcf3ce44SJohn Forte 		p = dbuf->db_sglist[0].seg_addr;
6931fcf3ce44SJohn Forte 
6932fcf3ce44SJohn Forte 		/*
6933fcf3ce44SJohn Forte 		 * Standard inquiry handling only.
6934fcf3ce44SJohn Forte 		 */
6935fcf3ce44SJohn Forte 
6936fcf3ce44SJohn Forte 		bzero(p, inq_page_length + 5);
6937fcf3ce44SJohn Forte 
6938fcf3ce44SJohn Forte 		p[0] = DPQ_SUPPORTED | DTYPE_UNKNOWN;
6939fcf3ce44SJohn Forte 		p[2] = 5;
6940fcf3ce44SJohn Forte 		p[3] = 0x12;
6941fcf3ce44SJohn Forte 		p[4] = inq_page_length;
6942fcf3ce44SJohn Forte 		p[6] = 0x80;
6943fcf3ce44SJohn Forte 
6944fcf3ce44SJohn Forte 		(void) strncpy((char *)p+8, "SUN     ", 8);
6945fcf3ce44SJohn Forte 		(void) strncpy((char *)p+16, "COMSTAR	       ", 16);
6946fcf3ce44SJohn Forte 		(void) strncpy((char *)p+32, "1.0 ", 4);
6947fcf3ce44SJohn Forte 
6948fcf3ce44SJohn Forte 		dbuf->db_data_size = sz;
6949fcf3ce44SJohn Forte 		dbuf->db_relative_offset = 0;
6950fcf3ce44SJohn Forte 		dbuf->db_flags = DB_DIRECTION_TO_RPORT;
6951fcf3ce44SJohn Forte 		(void) stmf_xfer_data(task, dbuf, 0);
6952fcf3ce44SJohn Forte 
6953fcf3ce44SJohn Forte 		return;
6954fcf3ce44SJohn Forte 
6955fcf3ce44SJohn Forte 	case SCMD_REPORT_LUNS:
6956fcf3ce44SJohn Forte 		task->task_cmd_xfer_length =
6957fcf3ce44SJohn Forte 		    ((((uint32_t)task->task_cdb[6]) << 24) |
6958fcf3ce44SJohn Forte 		    (((uint32_t)task->task_cdb[7]) << 16) |
6959fcf3ce44SJohn Forte 		    (((uint32_t)task->task_cdb[8]) << 8) |
6960fcf3ce44SJohn Forte 		    ((uint32_t)task->task_cdb[9]));
6961fcf3ce44SJohn Forte 
6962fcf3ce44SJohn Forte 		if (task->task_additional_flags &
6963fcf3ce44SJohn Forte 		    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
6964fcf3ce44SJohn Forte 			task->task_expected_xfer_length =
6965fcf3ce44SJohn Forte 			    task->task_cmd_xfer_length;
6966fcf3ce44SJohn Forte 		}
6967fcf3ce44SJohn Forte 
6968fcf3ce44SJohn Forte 		sz = min(task->task_expected_xfer_length,
6969fcf3ce44SJohn Forte 		    task->task_cmd_xfer_length);
6970fcf3ce44SJohn Forte 
6971fcf3ce44SJohn Forte 		if (sz < 16) {
6972fcf3ce44SJohn Forte 			stmf_scsilib_send_status(task, STATUS_CHECK,
6973fcf3ce44SJohn Forte 			    STMF_SAA_INVALID_FIELD_IN_CDB);
6974fcf3ce44SJohn Forte 			return;
6975fcf3ce44SJohn Forte 		}
6976fcf3ce44SJohn Forte 
6977fcf3ce44SJohn Forte 		iss = (stmf_i_scsi_session_t *)
6978fcf3ce44SJohn Forte 		    task->task_session->ss_stmf_private;
6979fcf3ce44SJohn Forte 		rw_enter(iss->iss_lockp, RW_WRITER);
6980fcf3ce44SJohn Forte 		xd = stmf_session_prepare_report_lun_data(iss->iss_sm);
6981fcf3ce44SJohn Forte 		rw_exit(iss->iss_lockp);
6982fcf3ce44SJohn Forte 
6983fcf3ce44SJohn Forte 		if (xd == NULL) {
6984fcf3ce44SJohn Forte 			stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6985fcf3ce44SJohn Forte 			    STMF_ALLOC_FAILURE, NULL);
6986fcf3ce44SJohn Forte 			return;
6987fcf3ce44SJohn Forte 		}
6988fcf3ce44SJohn Forte 
6989fcf3ce44SJohn Forte 		sz = min(sz, xd->size_left);
6990fcf3ce44SJohn Forte 		xd->size_left = sz;
6991fcf3ce44SJohn Forte 		minsz = min(512, sz);
6992fcf3ce44SJohn Forte 
6993fcf3ce44SJohn Forte 		if (dbuf == NULL)
6994fcf3ce44SJohn Forte 			dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0);
6995fcf3ce44SJohn Forte 		if (dbuf == NULL) {
6996fcf3ce44SJohn Forte 			kmem_free(xd, xd->alloc_size);
6997fcf3ce44SJohn Forte 			stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6998fcf3ce44SJohn Forte 			    STMF_ALLOC_FAILURE, NULL);
6999fcf3ce44SJohn Forte 			return;
7000fcf3ce44SJohn Forte 		}
7001fcf3ce44SJohn Forte 		dbuf->db_lu_private = xd;
700291159e90SJohn Forte 		stmf_xd_to_dbuf(dbuf, 1);
7003fcf3ce44SJohn Forte 
7004fcf3ce44SJohn Forte 		atomic_and_32(&iss->iss_flags,
7005fcf3ce44SJohn Forte 		    ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS));
7006fcf3ce44SJohn Forte 		dbuf->db_flags = DB_DIRECTION_TO_RPORT;
7007fcf3ce44SJohn Forte 		(void) stmf_xfer_data(task, dbuf, 0);
7008fcf3ce44SJohn Forte 		return;
7009fcf3ce44SJohn Forte 	}
7010fcf3ce44SJohn Forte 
7011fcf3ce44SJohn Forte 	stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE);
7012fcf3ce44SJohn Forte }
7013fcf3ce44SJohn Forte 
7014fcf3ce44SJohn Forte void
stmf_dlun0_dbuf_done(scsi_task_t * task,stmf_data_buf_t * dbuf)7015fcf3ce44SJohn Forte stmf_dlun0_dbuf_done(scsi_task_t *task, stmf_data_buf_t *dbuf)
7016fcf3ce44SJohn Forte {
701745039663SJohn Forte 	stmf_i_scsi_task_t *itask =
701845039663SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
701945039663SJohn Forte 
7020fcf3ce44SJohn Forte 	if (dbuf->db_xfer_status != STMF_SUCCESS) {
7021fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7022fcf3ce44SJohn Forte 		    dbuf->db_xfer_status, NULL);
7023fcf3ce44SJohn Forte 		return;
7024fcf3ce44SJohn Forte 	}
702591159e90SJohn Forte 	task->task_nbytes_transferred += dbuf->db_data_size;
7026fcf3ce44SJohn Forte 	if (dbuf->db_lu_private) {
7027fcf3ce44SJohn Forte 		/* There is more */
702891159e90SJohn Forte 		stmf_xd_to_dbuf(dbuf, 1);
7029fcf3ce44SJohn Forte 		(void) stmf_xfer_data(task, dbuf, 0);
7030fcf3ce44SJohn Forte 		return;
7031fcf3ce44SJohn Forte 	}
703291159e90SJohn Forte 
703391159e90SJohn Forte 	stmf_free_dbuf(task, dbuf);
703445039663SJohn Forte 	/*
703545039663SJohn Forte 	 * If this is a proxy task, it will need to be completed from the
703645039663SJohn Forte 	 * proxy port provider. This message lets pppt know that the xfer
703745039663SJohn Forte 	 * is complete. When we receive the status from pppt, we will
703845039663SJohn Forte 	 * then relay that status back to the lport.
703945039663SJohn Forte 	 */
704045039663SJohn Forte 	if (itask->itask_flags & ITASK_PROXY_TASK) {
704145039663SJohn Forte 		stmf_ic_msg_t *ic_xfer_done_msg = NULL;
704245039663SJohn Forte 		stmf_status_t ic_ret = STMF_FAILURE;
704345039663SJohn Forte 		uint64_t session_msg_id;
704445039663SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
704545039663SJohn Forte 		session_msg_id = stmf_proxy_msg_id++;
704645039663SJohn Forte 		mutex_exit(&stmf_state.stmf_lock);
704745039663SJohn Forte 		/* send xfer done status to pppt */
704845039663SJohn Forte 		ic_xfer_done_msg = ic_scsi_data_xfer_done_msg_alloc(
704945039663SJohn Forte 		    itask->itask_proxy_msg_id,
705045039663SJohn Forte 		    task->task_session->ss_session_id,
705145039663SJohn Forte 		    STMF_SUCCESS, session_msg_id);
705245039663SJohn Forte 		if (ic_xfer_done_msg) {
705345039663SJohn Forte 			ic_ret = ic_tx_msg(ic_xfer_done_msg);
705445039663SJohn Forte 			if (ic_ret != STMF_IC_MSG_SUCCESS) {
705545039663SJohn Forte 				cmn_err(CE_WARN, "unable to xmit session msg");
705645039663SJohn Forte 			}
705745039663SJohn Forte 		}
705845039663SJohn Forte 		/* task will be completed from pppt */
705945039663SJohn Forte 		return;
706045039663SJohn Forte 	}
7061fcf3ce44SJohn Forte 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
7062fcf3ce44SJohn Forte }
7063fcf3ce44SJohn Forte 
7064fcf3ce44SJohn Forte /* ARGSUSED */
7065fcf3ce44SJohn Forte void
stmf_dlun0_status_done(scsi_task_t * task)7066fcf3ce44SJohn Forte stmf_dlun0_status_done(scsi_task_t *task)
7067fcf3ce44SJohn Forte {
7068fcf3ce44SJohn Forte }
7069fcf3ce44SJohn Forte 
7070fcf3ce44SJohn Forte /* ARGSUSED */
7071fcf3ce44SJohn Forte void
stmf_dlun0_task_free(scsi_task_t * task)7072fcf3ce44SJohn Forte stmf_dlun0_task_free(scsi_task_t *task)
7073fcf3ce44SJohn Forte {
7074fcf3ce44SJohn Forte }
7075fcf3ce44SJohn Forte 
7076fcf3ce44SJohn Forte /* ARGSUSED */
7077fcf3ce44SJohn Forte stmf_status_t
stmf_dlun0_abort(struct stmf_lu * lu,int abort_cmd,void * arg,uint32_t flags)7078fcf3ce44SJohn Forte stmf_dlun0_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags)
7079fcf3ce44SJohn Forte {
7080fcf3ce44SJohn Forte 	scsi_task_t *task = (scsi_task_t *)arg;
7081fcf3ce44SJohn Forte 	stmf_i_scsi_task_t *itask =
7082fcf3ce44SJohn Forte 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
7083fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7084fcf3ce44SJohn Forte 	int i;
7085fcf3ce44SJohn Forte 	uint8_t map;
7086fcf3ce44SJohn Forte 
7087fcf3ce44SJohn Forte 	if ((task->task_mgmt_function) && (itask->itask_flags &
7088fcf3ce44SJohn Forte 	    (ITASK_CAUSING_LU_RESET | ITASK_CAUSING_TARGET_RESET))) {
7089fcf3ce44SJohn Forte 		switch (task->task_mgmt_function) {
7090fcf3ce44SJohn Forte 		case TM_ABORT_TASK:
7091fcf3ce44SJohn Forte 		case TM_ABORT_TASK_SET:
7092fcf3ce44SJohn Forte 		case TM_CLEAR_TASK_SET:
7093fcf3ce44SJohn Forte 		case TM_LUN_RESET:
7094fcf3ce44SJohn Forte 			atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
7095fcf3ce44SJohn Forte 			break;
7096fcf3ce44SJohn Forte 		case TM_TARGET_RESET:
7097fcf3ce44SJohn Forte 		case TM_TARGET_COLD_RESET:
7098fcf3ce44SJohn Forte 		case TM_TARGET_WARM_RESET:
7099fcf3ce44SJohn Forte 			stmf_abort_target_reset(task);
7100fcf3ce44SJohn Forte 			break;
7101fcf3ce44SJohn Forte 		}
7102fcf3ce44SJohn Forte 		return (STMF_ABORT_SUCCESS);
7103fcf3ce44SJohn Forte 	}
7104fcf3ce44SJohn Forte 
7105fcf3ce44SJohn Forte 	/*
7106fcf3ce44SJohn Forte 	 * OK so its not a task mgmt. Make sure we free any xd sitting
7107fcf3ce44SJohn Forte 	 * inside any dbuf.
7108fcf3ce44SJohn Forte 	 */
7109fcf3ce44SJohn Forte 	if ((map = itask->itask_allocated_buf_map) != 0) {
7110fcf3ce44SJohn Forte 		for (i = 0; i < 4; i++) {
7111fcf3ce44SJohn Forte 			if ((map & 1) &&
7112fcf3ce44SJohn Forte 			    ((itask->itask_dbufs[i])->db_lu_private)) {
7113fcf3ce44SJohn Forte 				stmf_xfer_data_t *xd;
7114fcf3ce44SJohn Forte 				stmf_data_buf_t *dbuf;
7115fcf3ce44SJohn Forte 
7116fcf3ce44SJohn Forte 				dbuf = itask->itask_dbufs[i];
7117fcf3ce44SJohn Forte 				xd = (stmf_xfer_data_t *)dbuf->db_lu_private;
7118fcf3ce44SJohn Forte 				dbuf->db_lu_private = NULL;
7119fcf3ce44SJohn Forte 				kmem_free(xd, xd->alloc_size);
7120fcf3ce44SJohn Forte 			}
7121fcf3ce44SJohn Forte 			map >>= 1;
7122fcf3ce44SJohn Forte 		}
7123fcf3ce44SJohn Forte 	}
7124fcf3ce44SJohn Forte 	return (STMF_ABORT_SUCCESS);
7125fcf3ce44SJohn Forte }
7126fcf3ce44SJohn Forte 
7127fcf3ce44SJohn Forte void
stmf_dlun0_task_poll(struct scsi_task * task)7128fcf3ce44SJohn Forte stmf_dlun0_task_poll(struct scsi_task *task)
7129fcf3ce44SJohn Forte {
7130fcf3ce44SJohn Forte 	/* Right now we only do this for handling task management functions */
7131fcf3ce44SJohn Forte 	ASSERT(task->task_mgmt_function);
7132fcf3ce44SJohn Forte 
7133fcf3ce44SJohn Forte 	switch (task->task_mgmt_function) {
7134fcf3ce44SJohn Forte 	case TM_ABORT_TASK:
7135fcf3ce44SJohn Forte 	case TM_ABORT_TASK_SET:
7136fcf3ce44SJohn Forte 	case TM_CLEAR_TASK_SET:
7137fcf3ce44SJohn Forte 	case TM_LUN_RESET:
7138fcf3ce44SJohn Forte 		(void) stmf_lun_reset_poll(task->task_lu, task, 0);
7139fcf3ce44SJohn Forte 		return;
7140fcf3ce44SJohn Forte 	case TM_TARGET_RESET:
7141fcf3ce44SJohn Forte 	case TM_TARGET_COLD_RESET:
7142fcf3ce44SJohn Forte 	case TM_TARGET_WARM_RESET:
7143fcf3ce44SJohn Forte 		stmf_target_reset_poll(task);
7144fcf3ce44SJohn Forte 		return;
7145fcf3ce44SJohn Forte 	}
7146fcf3ce44SJohn Forte }
7147fcf3ce44SJohn Forte 
7148fcf3ce44SJohn Forte /* ARGSUSED */
7149fcf3ce44SJohn Forte void
stmf_dlun0_ctl(struct stmf_lu * lu,int cmd,void * arg)7150fcf3ce44SJohn Forte stmf_dlun0_ctl(struct stmf_lu *lu, int cmd, void *arg)
7151fcf3ce44SJohn Forte {
7152fcf3ce44SJohn Forte 	/* This function will never be called */
7153fcf3ce44SJohn Forte 	cmn_err(CE_WARN, "stmf_dlun0_ctl called with cmd %x", cmd);
7154fcf3ce44SJohn Forte }
7155fcf3ce44SJohn Forte 
715661dfa509SRick McNeal /* ARGSUSED */
715761dfa509SRick McNeal void
stmf_dlun0_task_done(struct scsi_task * task)715861dfa509SRick McNeal stmf_dlun0_task_done(struct scsi_task *task)
715961dfa509SRick McNeal {
716061dfa509SRick McNeal }
716161dfa509SRick McNeal 
7162fcf3ce44SJohn Forte void
stmf_dlun_init()7163fcf3ce44SJohn Forte stmf_dlun_init()
7164fcf3ce44SJohn Forte {
7165fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
7166fcf3ce44SJohn Forte 
7167fcf3ce44SJohn Forte 	dlun0 = stmf_alloc(STMF_STRUCT_STMF_LU, 0, 0);
7168fcf3ce44SJohn Forte 	dlun0->lu_task_alloc = stmf_dlun0_task_alloc;
7169fcf3ce44SJohn Forte 	dlun0->lu_new_task = stmf_dlun0_new_task;
7170fcf3ce44SJohn Forte 	dlun0->lu_dbuf_xfer_done = stmf_dlun0_dbuf_done;
7171fcf3ce44SJohn Forte 	dlun0->lu_send_status_done = stmf_dlun0_status_done;
7172fcf3ce44SJohn Forte 	dlun0->lu_task_free = stmf_dlun0_task_free;
7173fcf3ce44SJohn Forte 	dlun0->lu_abort = stmf_dlun0_abort;
7174fcf3ce44SJohn Forte 	dlun0->lu_task_poll = stmf_dlun0_task_poll;
7175fcf3ce44SJohn Forte 	dlun0->lu_ctl = stmf_dlun0_ctl;
717661dfa509SRick McNeal 	dlun0->lu_task_done = stmf_dlun0_task_done;
7177fcf3ce44SJohn Forte 
7178fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private;
7179fcf3ce44SJohn Forte 	ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
7180fcf3ce44SJohn Forte }
7181fcf3ce44SJohn Forte 
7182fcf3ce44SJohn Forte stmf_status_t
stmf_dlun_fini()7183fcf3ce44SJohn Forte stmf_dlun_fini()
7184fcf3ce44SJohn Forte {
7185fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
7186fcf3ce44SJohn Forte 
7187fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private;
7188fcf3ce44SJohn Forte 
7189fcf3ce44SJohn Forte 	ASSERT(ilu->ilu_ntasks == ilu->ilu_ntasks_free);
7190fcf3ce44SJohn Forte 	if (ilu->ilu_ntasks) {
7191fcf3ce44SJohn Forte 		stmf_i_scsi_task_t *itask, *nitask;
7192fcf3ce44SJohn Forte 
7193fcf3ce44SJohn Forte 		nitask = ilu->ilu_tasks;
7194fcf3ce44SJohn Forte 		do {
7195fcf3ce44SJohn Forte 			itask = nitask;
7196fcf3ce44SJohn Forte 			nitask = itask->itask_lu_next;
7197fcf3ce44SJohn Forte 			dlun0->lu_task_free(itask->itask_task);
7198fcf3ce44SJohn Forte 			stmf_free(itask->itask_task);
7199fcf3ce44SJohn Forte 		} while (nitask != NULL);
7200fcf3ce44SJohn Forte 
7201fcf3ce44SJohn Forte 	}
7202fcf3ce44SJohn Forte 	stmf_free(dlun0);
7203fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
7204fcf3ce44SJohn Forte }
7205fcf3ce44SJohn Forte 
7206fcf3ce44SJohn Forte void
stmf_abort_target_reset(scsi_task_t * task)7207fcf3ce44SJohn Forte stmf_abort_target_reset(scsi_task_t *task)
7208fcf3ce44SJohn Forte {
7209fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
7210fcf3ce44SJohn Forte 	    task->task_session->ss_stmf_private;
7211fcf3ce44SJohn Forte 	stmf_lun_map_t *lm;
7212fcf3ce44SJohn Forte 	stmf_lun_map_ent_t *lm_ent;
7213fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
7214fcf3ce44SJohn Forte 	int i;
7215fcf3ce44SJohn Forte 
7216fcf3ce44SJohn Forte 	rw_enter(iss->iss_lockp, RW_READER);
7217fcf3ce44SJohn Forte 	lm = iss->iss_sm;
7218fcf3ce44SJohn Forte 	for (i = 0; i < lm->lm_nentries; i++) {
7219fcf3ce44SJohn Forte 		if (lm->lm_plus[i] == NULL)
7220fcf3ce44SJohn Forte 			continue;
7221fcf3ce44SJohn Forte 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
7222fcf3ce44SJohn Forte 		ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private;
7223fcf3ce44SJohn Forte 		if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
7224fcf3ce44SJohn Forte 			atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
7225fcf3ce44SJohn Forte 		}
7226fcf3ce44SJohn Forte 	}
7227fcf3ce44SJohn Forte 	atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
7228fcf3ce44SJohn Forte 	rw_exit(iss->iss_lockp);
7229fcf3ce44SJohn Forte }
7230fcf3ce44SJohn Forte 
7231fcf3ce44SJohn Forte /*
7232fcf3ce44SJohn Forte  * The return value is only used by function managing target reset.
7233fcf3ce44SJohn Forte  */
7234fcf3ce44SJohn Forte stmf_status_t
stmf_lun_reset_poll(stmf_lu_t * lu,struct scsi_task * task,int target_reset)7235fcf3ce44SJohn Forte stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task, int target_reset)
7236fcf3ce44SJohn Forte {
7237fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7238fcf3ce44SJohn Forte 	int ntasks_pending;
7239fcf3ce44SJohn Forte 
7240fcf3ce44SJohn Forte 	ntasks_pending = ilu->ilu_ntasks - ilu->ilu_ntasks_free;
7241fcf3ce44SJohn Forte 	/*
7242fcf3ce44SJohn Forte 	 * This function is also used during Target reset. The idea is that
7243fcf3ce44SJohn Forte 	 * once all the commands are aborted, call the LU's reset entry
7244fcf3ce44SJohn Forte 	 * point (abort entry point with a reset flag). But if this Task
7245fcf3ce44SJohn Forte 	 * mgmt is running on this LU then all the tasks cannot be aborted.
7246fcf3ce44SJohn Forte 	 * one task (this task) will still be running which is OK.
7247fcf3ce44SJohn Forte 	 */
7248fcf3ce44SJohn Forte 	if ((ntasks_pending == 0) || ((task->task_lu == lu) &&
7249fcf3ce44SJohn Forte 	    (ntasks_pending == 1))) {
7250fcf3ce44SJohn Forte 		stmf_status_t ret;
7251fcf3ce44SJohn Forte 
7252fcf3ce44SJohn Forte 		if ((task->task_mgmt_function == TM_LUN_RESET) ||
7253fcf3ce44SJohn Forte 		    (task->task_mgmt_function == TM_TARGET_RESET) ||
7254fcf3ce44SJohn Forte 		    (task->task_mgmt_function == TM_TARGET_WARM_RESET) ||
7255fcf3ce44SJohn Forte 		    (task->task_mgmt_function == TM_TARGET_COLD_RESET)) {
7256fcf3ce44SJohn Forte 			ret = lu->lu_abort(lu, STMF_LU_RESET_STATE, task, 0);
7257fcf3ce44SJohn Forte 		} else {
7258fcf3ce44SJohn Forte 			ret = STMF_SUCCESS;
7259fcf3ce44SJohn Forte 		}
7260fcf3ce44SJohn Forte 		if (ret == STMF_SUCCESS) {
7261fcf3ce44SJohn Forte 			atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
7262fcf3ce44SJohn Forte 		}
7263fcf3ce44SJohn Forte 		if (target_reset) {
7264fcf3ce44SJohn Forte 			return (ret);
7265fcf3ce44SJohn Forte 		}
7266fcf3ce44SJohn Forte 		if (ret == STMF_SUCCESS) {
7267fcf3ce44SJohn Forte 			stmf_scsilib_send_status(task, STATUS_GOOD, 0);
7268fcf3ce44SJohn Forte 			return (ret);
7269fcf3ce44SJohn Forte 		}
7270fcf3ce44SJohn Forte 		if (ret != STMF_BUSY) {
7271fcf3ce44SJohn Forte 			stmf_abort(STMF_QUEUE_TASK_ABORT, task, ret, NULL);
7272fcf3ce44SJohn Forte 			return (ret);
7273fcf3ce44SJohn Forte 		}
7274fcf3ce44SJohn Forte 	}
7275fcf3ce44SJohn Forte 
7276fcf3ce44SJohn Forte 	if (target_reset) {
7277fcf3ce44SJohn Forte 		/* Tell target reset polling code that we are not done */
7278fcf3ce44SJohn Forte 		return (STMF_BUSY);
7279fcf3ce44SJohn Forte 	}
7280fcf3ce44SJohn Forte 
7281fcf3ce44SJohn Forte 	if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
7282fcf3ce44SJohn Forte 	    != STMF_SUCCESS) {
7283fcf3ce44SJohn Forte 		stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7284fcf3ce44SJohn Forte 		    STMF_ALLOC_FAILURE, NULL);
7285fcf3ce44SJohn Forte 		return (STMF_SUCCESS);
7286fcf3ce44SJohn Forte 	}
7287fcf3ce44SJohn Forte 
7288fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
7289fcf3ce44SJohn Forte }
7290fcf3ce44SJohn Forte 
7291fcf3ce44SJohn Forte void
stmf_target_reset_poll(struct scsi_task * task)7292fcf3ce44SJohn Forte stmf_target_reset_poll(struct scsi_task *task)
7293fcf3ce44SJohn Forte {
7294fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
7295fcf3ce44SJohn Forte 	    task->task_session->ss_stmf_private;
7296fcf3ce44SJohn Forte 	stmf_lun_map_t *lm;
7297fcf3ce44SJohn Forte 	stmf_lun_map_ent_t *lm_ent;
7298fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
7299fcf3ce44SJohn Forte 	stmf_status_t ret;
7300fcf3ce44SJohn Forte 	int i;
7301fcf3ce44SJohn Forte 	int not_done = 0;
7302fcf3ce44SJohn Forte 
7303fcf3ce44SJohn Forte 	ASSERT(iss->iss_flags & ISS_RESET_ACTIVE);
7304fcf3ce44SJohn Forte 
7305fcf3ce44SJohn Forte 	rw_enter(iss->iss_lockp, RW_READER);
7306fcf3ce44SJohn Forte 	lm = iss->iss_sm;
7307fcf3ce44SJohn Forte 	for (i = 0; i < lm->lm_nentries; i++) {
7308fcf3ce44SJohn Forte 		if (lm->lm_plus[i] == NULL)
7309fcf3ce44SJohn Forte 			continue;
7310fcf3ce44SJohn Forte 		lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
7311fcf3ce44SJohn Forte 		ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private;
7312fcf3ce44SJohn Forte 		if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
7313fcf3ce44SJohn Forte 			rw_exit(iss->iss_lockp);
7314fcf3ce44SJohn Forte 			ret = stmf_lun_reset_poll(lm_ent->ent_lu, task, 1);
7315fcf3ce44SJohn Forte 			rw_enter(iss->iss_lockp, RW_READER);
7316fcf3ce44SJohn Forte 			if (ret == STMF_SUCCESS)
7317fcf3ce44SJohn Forte 				continue;
7318fcf3ce44SJohn Forte 			not_done = 1;
7319fcf3ce44SJohn Forte 			if (ret != STMF_BUSY) {
7320fcf3ce44SJohn Forte 				rw_exit(iss->iss_lockp);
7321fcf3ce44SJohn Forte 				stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7322fcf3ce44SJohn Forte 				    STMF_ABORTED, NULL);
7323fcf3ce44SJohn Forte 				return;
7324fcf3ce44SJohn Forte 			}
7325fcf3ce44SJohn Forte 		}
7326fcf3ce44SJohn Forte 	}
7327fcf3ce44SJohn Forte 	rw_exit(iss->iss_lockp);
7328fcf3ce44SJohn Forte 
7329fcf3ce44SJohn Forte 	if (not_done) {
7330fcf3ce44SJohn Forte 		if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
7331fcf3ce44SJohn Forte 		    != STMF_SUCCESS) {
7332fcf3ce44SJohn Forte 			stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7333fcf3ce44SJohn Forte 			    STMF_ALLOC_FAILURE, NULL);
7334fcf3ce44SJohn Forte 			return;
7335fcf3ce44SJohn Forte 		}
7336fcf3ce44SJohn Forte 		return;
7337fcf3ce44SJohn Forte 	}
7338fcf3ce44SJohn Forte 
7339fcf3ce44SJohn Forte 	atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
7340fcf3ce44SJohn Forte 
7341fcf3ce44SJohn Forte 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
7342fcf3ce44SJohn Forte }
7343fcf3ce44SJohn Forte 
7344fcf3ce44SJohn Forte stmf_status_t
stmf_lu_add_event(stmf_lu_t * lu,int eventid)7345fcf3ce44SJohn Forte stmf_lu_add_event(stmf_lu_t *lu, int eventid)
7346fcf3ce44SJohn Forte {
7347fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7348fcf3ce44SJohn Forte 
7349fcf3ce44SJohn Forte 	if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7350fcf3ce44SJohn Forte 		return (STMF_INVALID_ARG);
7351fcf3ce44SJohn Forte 	}
7352fcf3ce44SJohn Forte 
7353fcf3ce44SJohn Forte 	STMF_EVENT_ADD(ilu->ilu_event_hdl, eventid);
7354fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
7355fcf3ce44SJohn Forte }
7356fcf3ce44SJohn Forte 
7357fcf3ce44SJohn Forte stmf_status_t
stmf_lu_remove_event(stmf_lu_t * lu,int eventid)7358fcf3ce44SJohn Forte stmf_lu_remove_event(stmf_lu_t *lu, int eventid)
7359fcf3ce44SJohn Forte {
7360fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7361fcf3ce44SJohn Forte 
7362fcf3ce44SJohn Forte 	if (eventid == STMF_EVENT_ALL) {
7363fcf3ce44SJohn Forte 		STMF_EVENT_CLEAR_ALL(ilu->ilu_event_hdl);
7364fcf3ce44SJohn Forte 		return (STMF_SUCCESS);
7365fcf3ce44SJohn Forte 	}
7366fcf3ce44SJohn Forte 
7367fcf3ce44SJohn Forte 	if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7368fcf3ce44SJohn Forte 		return (STMF_INVALID_ARG);
7369fcf3ce44SJohn Forte 	}
7370fcf3ce44SJohn Forte 
7371fcf3ce44SJohn Forte 	STMF_EVENT_REMOVE(ilu->ilu_event_hdl, eventid);
7372fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
7373fcf3ce44SJohn Forte }
7374fcf3ce44SJohn Forte 
7375fcf3ce44SJohn Forte stmf_status_t
stmf_lport_add_event(stmf_local_port_t * lport,int eventid)7376fcf3ce44SJohn Forte stmf_lport_add_event(stmf_local_port_t *lport, int eventid)
7377fcf3ce44SJohn Forte {
7378fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport =
7379fcf3ce44SJohn Forte 	    (stmf_i_local_port_t *)lport->lport_stmf_private;
7380fcf3ce44SJohn Forte 
7381fcf3ce44SJohn Forte 	if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7382fcf3ce44SJohn Forte 		return (STMF_INVALID_ARG);
7383fcf3ce44SJohn Forte 	}
7384fcf3ce44SJohn Forte 
7385fcf3ce44SJohn Forte 	STMF_EVENT_ADD(ilport->ilport_event_hdl, eventid);
7386fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
7387fcf3ce44SJohn Forte }
7388fcf3ce44SJohn Forte 
7389fcf3ce44SJohn Forte stmf_status_t
stmf_lport_remove_event(stmf_local_port_t * lport,int eventid)7390fcf3ce44SJohn Forte stmf_lport_remove_event(stmf_local_port_t *lport, int eventid)
7391fcf3ce44SJohn Forte {
7392fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport =
7393fcf3ce44SJohn Forte 	    (stmf_i_local_port_t *)lport->lport_stmf_private;
7394fcf3ce44SJohn Forte 
7395fcf3ce44SJohn Forte 	if (eventid == STMF_EVENT_ALL) {
7396fcf3ce44SJohn Forte 		STMF_EVENT_CLEAR_ALL(ilport->ilport_event_hdl);
7397fcf3ce44SJohn Forte 		return (STMF_SUCCESS);
7398fcf3ce44SJohn Forte 	}
7399fcf3ce44SJohn Forte 
7400fcf3ce44SJohn Forte 	if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7401fcf3ce44SJohn Forte 		return (STMF_INVALID_ARG);
7402fcf3ce44SJohn Forte 	}
7403fcf3ce44SJohn Forte 
7404fcf3ce44SJohn Forte 	STMF_EVENT_REMOVE(ilport->ilport_event_hdl, eventid);
7405fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
7406fcf3ce44SJohn Forte }
7407fcf3ce44SJohn Forte 
7408fcf3ce44SJohn Forte void
stmf_generate_lu_event(stmf_i_lu_t * ilu,int eventid,void * arg,uint32_t flags)7409fcf3ce44SJohn Forte stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid, void *arg, uint32_t flags)
7410fcf3ce44SJohn Forte {
7411fcf3ce44SJohn Forte 	if (STMF_EVENT_ENABLED(ilu->ilu_event_hdl, eventid) &&
7412fcf3ce44SJohn Forte 	    (ilu->ilu_lu->lu_event_handler != NULL)) {
7413fcf3ce44SJohn Forte 		ilu->ilu_lu->lu_event_handler(ilu->ilu_lu, eventid, arg, flags);
7414fcf3ce44SJohn Forte 	}
7415fcf3ce44SJohn Forte }
7416fcf3ce44SJohn Forte 
7417fcf3ce44SJohn Forte void
stmf_generate_lport_event(stmf_i_local_port_t * ilport,int eventid,void * arg,uint32_t flags)7418fcf3ce44SJohn Forte stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid, void *arg,
7419fcf3ce44SJohn Forte     uint32_t flags)
7420fcf3ce44SJohn Forte {
7421fcf3ce44SJohn Forte 	if (STMF_EVENT_ENABLED(ilport->ilport_event_hdl, eventid) &&
7422fcf3ce44SJohn Forte 	    (ilport->ilport_lport->lport_event_handler != NULL)) {
7423fcf3ce44SJohn Forte 		ilport->ilport_lport->lport_event_handler(
7424fcf3ce44SJohn Forte 		    ilport->ilport_lport, eventid, arg, flags);
7425fcf3ce44SJohn Forte 	}
7426fcf3ce44SJohn Forte }
7427fcf3ce44SJohn Forte 
7428427fcaf8Stim szeto /*
7429427fcaf8Stim szeto  * With the possibility of having multiple itl sessions pointing to the
7430427fcaf8Stim szeto  * same itl_kstat_info, the ilu_kstat_lock mutex is used to synchronize
7431427fcaf8Stim szeto  * the kstat update of the ilu_kstat_io, itl_kstat_taskq and itl_kstat_lu_xfer
7432427fcaf8Stim szeto  * statistics.
7433427fcaf8Stim szeto  */
7434427fcaf8Stim szeto void
stmf_itl_task_start(stmf_i_scsi_task_t * itask)7435427fcaf8Stim szeto stmf_itl_task_start(stmf_i_scsi_task_t *itask)
7436427fcaf8Stim szeto {
7437427fcaf8Stim szeto 	stmf_itl_data_t	*itl = itask->itask_itl_datap;
7438427fcaf8Stim szeto 	scsi_task_t	*task = itask->itask_task;
7439427fcaf8Stim szeto 	stmf_i_lu_t	*ilu;
744061dfa509SRick McNeal 	stmf_i_scsi_session_t   *iss =
744161dfa509SRick McNeal 	    itask->itask_task->task_session->ss_stmf_private;
744261dfa509SRick McNeal 	stmf_i_remote_port_t    *irport = iss->iss_irport;
7443427fcaf8Stim szeto 
7444427fcaf8Stim szeto 	if (itl == NULL || task->task_lu == dlun0)
7445427fcaf8Stim szeto 		return;
7446427fcaf8Stim szeto 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7447427fcaf8Stim szeto 	itask->itask_start_timestamp = gethrtime();
744861dfa509SRick McNeal 	itask->itask_xfer_done_timestamp = 0;
744909409df0SJeff Biseda 	if (ilu->ilu_kstat_io != NULL) {
745009409df0SJeff Biseda 		mutex_enter(ilu->ilu_kstat_io->ks_lock);
7451427fcaf8Stim szeto 		stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_enter);
7452427fcaf8Stim szeto 		mutex_exit(ilu->ilu_kstat_io->ks_lock);
745309409df0SJeff Biseda 	}
7454427fcaf8Stim szeto 
745561dfa509SRick McNeal 	if (irport->irport_kstat_estat != NULL) {
745661dfa509SRick McNeal 		if (task->task_flags & TF_READ_DATA)
745761dfa509SRick McNeal 			atomic_inc_32(&irport->irport_nread_tasks);
745861dfa509SRick McNeal 		else if (task->task_flags & TF_WRITE_DATA)
745961dfa509SRick McNeal 			atomic_inc_32(&irport->irport_nwrite_tasks);
746061dfa509SRick McNeal 	}
746161dfa509SRick McNeal 
7462427fcaf8Stim szeto 	stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_enter);
7463427fcaf8Stim szeto }
7464427fcaf8Stim szeto 
7465427fcaf8Stim szeto void
stmf_itl_lu_new_task(stmf_i_scsi_task_t * itask)7466427fcaf8Stim szeto stmf_itl_lu_new_task(stmf_i_scsi_task_t *itask)
7467427fcaf8Stim szeto {
7468427fcaf8Stim szeto 	stmf_itl_data_t	*itl = itask->itask_itl_datap;
7469427fcaf8Stim szeto 	scsi_task_t	*task = itask->itask_task;
7470427fcaf8Stim szeto 	stmf_i_lu_t	*ilu;
7471427fcaf8Stim szeto 
7472427fcaf8Stim szeto 	if (itl == NULL || task->task_lu == dlun0)
7473427fcaf8Stim szeto 		return;
7474427fcaf8Stim szeto 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
747509409df0SJeff Biseda 	if (ilu->ilu_kstat_io != NULL) {
7476427fcaf8Stim szeto 		mutex_enter(ilu->ilu_kstat_io->ks_lock);
7477427fcaf8Stim szeto 		stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_to_runq);
7478427fcaf8Stim szeto 		mutex_exit(ilu->ilu_kstat_io->ks_lock);
747909409df0SJeff Biseda 	}
7480427fcaf8Stim szeto 
7481427fcaf8Stim szeto 	stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_to_runq);
7482427fcaf8Stim szeto }
7483427fcaf8Stim szeto 
7484427fcaf8Stim szeto void
stmf_itl_task_done(stmf_i_scsi_task_t * itask)7485427fcaf8Stim szeto stmf_itl_task_done(stmf_i_scsi_task_t *itask)
7486427fcaf8Stim szeto {
7487427fcaf8Stim szeto 	stmf_itl_data_t		*itl = itask->itask_itl_datap;
7488427fcaf8Stim szeto 	scsi_task_t		*task = itask->itask_task;
7489427fcaf8Stim szeto 	stmf_i_lu_t	*ilu;
7490427fcaf8Stim szeto 
749109409df0SJeff Biseda 	itask->itask_done_timestamp = gethrtime();
749209409df0SJeff Biseda 
7493427fcaf8Stim szeto 	if (itl == NULL || task->task_lu == dlun0)
7494427fcaf8Stim szeto 		return;
7495427fcaf8Stim szeto 	ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7496427fcaf8Stim szeto 
749709409df0SJeff Biseda 	if (ilu->ilu_kstat_io == NULL)
749809409df0SJeff Biseda 		return;
749909409df0SJeff Biseda 
750061dfa509SRick McNeal 	stmf_update_kstat_rport_estat(task);
750161dfa509SRick McNeal 
7502427fcaf8Stim szeto 	mutex_enter(ilu->ilu_kstat_io->ks_lock);
7503427fcaf8Stim szeto 
7504427fcaf8Stim szeto 	if (itask->itask_flags & ITASK_KSTAT_IN_RUNQ) {
7505427fcaf8Stim szeto 		stmf_update_kstat_lu_q(task, kstat_runq_exit);
7506427fcaf8Stim szeto 		mutex_exit(ilu->ilu_kstat_io->ks_lock);
7507427fcaf8Stim szeto 		stmf_update_kstat_lport_q(task, kstat_runq_exit);
7508427fcaf8Stim szeto 	} else {
7509427fcaf8Stim szeto 		stmf_update_kstat_lu_q(task, kstat_waitq_exit);
7510427fcaf8Stim szeto 		mutex_exit(ilu->ilu_kstat_io->ks_lock);
7511427fcaf8Stim szeto 		stmf_update_kstat_lport_q(task, kstat_waitq_exit);
7512427fcaf8Stim szeto 	}
7513427fcaf8Stim szeto }
7514427fcaf8Stim szeto 
751561dfa509SRick McNeal void
stmf_lu_xfer_done(scsi_task_t * task,boolean_t read,hrtime_t elapsed_time)751661dfa509SRick McNeal stmf_lu_xfer_done(scsi_task_t *task, boolean_t read, hrtime_t elapsed_time)
751761dfa509SRick McNeal {
751861dfa509SRick McNeal 	stmf_i_scsi_task_t *itask = task->task_stmf_private;
751961dfa509SRick McNeal 
752061dfa509SRick McNeal 	if (task->task_lu == dlun0)
752161dfa509SRick McNeal 		return;
752261dfa509SRick McNeal 
752361dfa509SRick McNeal 	if (read) {
752461dfa509SRick McNeal 		atomic_add_64((uint64_t *)&itask->itask_lu_read_time,
752561dfa509SRick McNeal 		    elapsed_time);
752661dfa509SRick McNeal 	} else {
752761dfa509SRick McNeal 		atomic_add_64((uint64_t *)&itask->itask_lu_write_time,
752861dfa509SRick McNeal 		    elapsed_time);
752961dfa509SRick McNeal 	}
753061dfa509SRick McNeal }
753161dfa509SRick McNeal 
7532427fcaf8Stim szeto static void
stmf_lport_xfer_start(stmf_i_scsi_task_t * itask,stmf_data_buf_t * dbuf)7533427fcaf8Stim szeto stmf_lport_xfer_start(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7534427fcaf8Stim szeto {
7535427fcaf8Stim szeto 	stmf_itl_data_t		*itl = itask->itask_itl_datap;
7536427fcaf8Stim szeto 
7537427fcaf8Stim szeto 	if (itl == NULL)
7538427fcaf8Stim szeto 		return;
7539427fcaf8Stim szeto 
7540427fcaf8Stim szeto 	DTRACE_PROBE2(scsi__xfer__start, scsi_task_t *, itask->itask_task,
7541427fcaf8Stim szeto 	    stmf_data_buf_t *, dbuf);
7542427fcaf8Stim szeto 
7543427fcaf8Stim szeto 	dbuf->db_xfer_start_timestamp = gethrtime();
7544427fcaf8Stim szeto }
7545427fcaf8Stim szeto 
7546427fcaf8Stim szeto static void
stmf_lport_xfer_done(stmf_i_scsi_task_t * itask,stmf_data_buf_t * dbuf)7547427fcaf8Stim szeto stmf_lport_xfer_done(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7548427fcaf8Stim szeto {
7549427fcaf8Stim szeto 	stmf_itl_data_t		*itl = itask->itask_itl_datap;
7550427fcaf8Stim szeto 	hrtime_t		elapsed_time;
7551427fcaf8Stim szeto 	uint64_t		xfer_size;
7552427fcaf8Stim szeto 
7553427fcaf8Stim szeto 	if (itl == NULL)
7554427fcaf8Stim szeto 		return;
7555427fcaf8Stim szeto 
7556427fcaf8Stim szeto 	xfer_size = (dbuf->db_xfer_status == STMF_SUCCESS) ?
7557427fcaf8Stim szeto 	    dbuf->db_data_size : 0;
7558427fcaf8Stim szeto 
755961dfa509SRick McNeal 	itask->itask_xfer_done_timestamp = gethrtime();
756061dfa509SRick McNeal 	elapsed_time = itask->itask_xfer_done_timestamp -
756161dfa509SRick McNeal 	    dbuf->db_xfer_start_timestamp;
7562427fcaf8Stim szeto 	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
7563427fcaf8Stim szeto 		atomic_add_64((uint64_t *)&itask->itask_lport_read_time,
7564427fcaf8Stim szeto 		    elapsed_time);
7565427fcaf8Stim szeto 		atomic_add_64((uint64_t *)&itask->itask_read_xfer,
7566427fcaf8Stim szeto 		    xfer_size);
7567427fcaf8Stim szeto 	} else {
7568427fcaf8Stim szeto 		atomic_add_64((uint64_t *)&itask->itask_lport_write_time,
7569427fcaf8Stim szeto 		    elapsed_time);
7570427fcaf8Stim szeto 		atomic_add_64((uint64_t *)&itask->itask_write_xfer,
7571427fcaf8Stim szeto 		    xfer_size);
7572427fcaf8Stim szeto 	}
7573427fcaf8Stim szeto 
7574427fcaf8Stim szeto 	DTRACE_PROBE3(scsi__xfer__end, scsi_task_t *, itask->itask_task,
7575427fcaf8Stim szeto 	    stmf_data_buf_t *, dbuf, hrtime_t, elapsed_time);
7576427fcaf8Stim szeto 
7577427fcaf8Stim szeto 	dbuf->db_xfer_start_timestamp = 0;
7578427fcaf8Stim szeto }
7579427fcaf8Stim szeto 
7580fcf3ce44SJohn Forte void
stmf_svc_init()7581fcf3ce44SJohn Forte stmf_svc_init()
7582fcf3ce44SJohn Forte {
7583fcf3ce44SJohn Forte 	if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
7584fcf3ce44SJohn Forte 		return;
758561dfa509SRick McNeal 	list_create(&stmf_state.stmf_svc_list, sizeof (stmf_svc_req_t),
758661dfa509SRick McNeal 	    offsetof(stmf_svc_req_t, svc_list_entry));
7587fcf3ce44SJohn Forte 	stmf_state.stmf_svc_taskq = ddi_taskq_create(0, "STMF_SVC_TASKQ", 1,
7588fcf3ce44SJohn Forte 	    TASKQ_DEFAULTPRI, 0);
7589fcf3ce44SJohn Forte 	(void) ddi_taskq_dispatch(stmf_state.stmf_svc_taskq,
7590fcf3ce44SJohn Forte 	    stmf_svc, 0, DDI_SLEEP);
7591fcf3ce44SJohn Forte }
7592fcf3ce44SJohn Forte 
7593fcf3ce44SJohn Forte stmf_status_t
stmf_svc_fini()7594fcf3ce44SJohn Forte stmf_svc_fini()
7595fcf3ce44SJohn Forte {
7596fcf3ce44SJohn Forte 	uint32_t i;
7597fcf3ce44SJohn Forte 
7598fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
7599fcf3ce44SJohn Forte 	if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) {
7600fcf3ce44SJohn Forte 		stmf_state.stmf_svc_flags |= STMF_SVC_TERMINATE;
7601fcf3ce44SJohn Forte 		cv_signal(&stmf_state.stmf_cv);
7602fcf3ce44SJohn Forte 	}
7603fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
7604fcf3ce44SJohn Forte 
7605fcf3ce44SJohn Forte 	/* Wait for 5 seconds */
7606fcf3ce44SJohn Forte 	for (i = 0; i < 500; i++) {
7607fcf3ce44SJohn Forte 		if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
7608fcf3ce44SJohn Forte 			delay(drv_usectohz(10000));
7609fcf3ce44SJohn Forte 		else
7610fcf3ce44SJohn Forte 			break;
7611fcf3ce44SJohn Forte 	}
7612fcf3ce44SJohn Forte 	if (i == 500)
7613fcf3ce44SJohn Forte 		return (STMF_BUSY);
7614fcf3ce44SJohn Forte 
761561dfa509SRick McNeal 	list_destroy(&stmf_state.stmf_svc_list);
7616fcf3ce44SJohn Forte 	ddi_taskq_destroy(stmf_state.stmf_svc_taskq);
7617fcf3ce44SJohn Forte 
7618fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
7619fcf3ce44SJohn Forte }
7620fcf3ce44SJohn Forte 
7621042f029eSAlexander Stetsenko struct stmf_svc_clocks {
7622042f029eSAlexander Stetsenko 	clock_t drain_start, drain_next;
7623042f029eSAlexander Stetsenko 	clock_t timing_start, timing_next;
7624042f029eSAlexander Stetsenko 	clock_t worker_delay;
7625042f029eSAlexander Stetsenko };
7626042f029eSAlexander Stetsenko 
7627fcf3ce44SJohn Forte /* ARGSUSED */
7628fcf3ce44SJohn Forte void
stmf_svc(void * arg)7629fcf3ce44SJohn Forte stmf_svc(void *arg)
7630fcf3ce44SJohn Forte {
76316ac72a9cSAlexander Stetsenko 	stmf_svc_req_t *req;
7632fcf3ce44SJohn Forte 	stmf_lu_t *lu;
7633fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
7634fcf3ce44SJohn Forte 	stmf_local_port_t *lport;
7635042f029eSAlexander Stetsenko 	struct stmf_svc_clocks clks = { 0 };
7636fcf3ce44SJohn Forte 
7637fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
7638fcf3ce44SJohn Forte 	stmf_state.stmf_svc_flags |= STMF_SVC_STARTED | STMF_SVC_ACTIVE;
7639fcf3ce44SJohn Forte 
76406ac72a9cSAlexander Stetsenko 	while (!(stmf_state.stmf_svc_flags & STMF_SVC_TERMINATE)) {
764161dfa509SRick McNeal 		if (list_is_empty(&stmf_state.stmf_svc_list)) {
7642042f029eSAlexander Stetsenko 			stmf_svc_timeout(&clks);
76436ac72a9cSAlexander Stetsenko 			continue;
7644fcf3ce44SJohn Forte 		}
7645fcf3ce44SJohn Forte 
76466ac72a9cSAlexander Stetsenko 		/*
76476ac72a9cSAlexander Stetsenko 		 * Pop the front request from the active list.  After this,
76486ac72a9cSAlexander Stetsenko 		 * the request will no longer be referenced by global state,
76496ac72a9cSAlexander Stetsenko 		 * so it should be safe to access it without holding the
76506ac72a9cSAlexander Stetsenko 		 * stmf state lock.
76516ac72a9cSAlexander Stetsenko 		 */
765261dfa509SRick McNeal 		req = list_remove_head(&stmf_state.stmf_svc_list);
765361dfa509SRick McNeal 		if (req == NULL)
765461dfa509SRick McNeal 			continue;
76556ac72a9cSAlexander Stetsenko 
7656fcf3ce44SJohn Forte 		switch (req->svc_cmd) {
7657fcf3ce44SJohn Forte 		case STMF_CMD_LPORT_ONLINE:
7658fcf3ce44SJohn Forte 			/* Fallthrough */
7659fcf3ce44SJohn Forte 		case STMF_CMD_LPORT_OFFLINE:
76606ac72a9cSAlexander Stetsenko 			mutex_exit(&stmf_state.stmf_lock);
76616ac72a9cSAlexander Stetsenko 			lport = (stmf_local_port_t *)req->svc_obj;
76626ac72a9cSAlexander Stetsenko 			lport->lport_ctl(lport, req->svc_cmd, &req->svc_info);
7663fcf3ce44SJohn Forte 			break;
76646ac72a9cSAlexander Stetsenko 		case STMF_CMD_LU_ONLINE:
76656ac72a9cSAlexander Stetsenko 			mutex_exit(&stmf_state.stmf_lock);
76666ac72a9cSAlexander Stetsenko 			lu = (stmf_lu_t *)req->svc_obj;
76676ac72a9cSAlexander Stetsenko 			lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
76686ac72a9cSAlexander Stetsenko 			break;
7669fcf3ce44SJohn Forte 		case STMF_CMD_LU_OFFLINE:
7670fcf3ce44SJohn Forte 			/* Remove all mappings of this LU */
7671fcf3ce44SJohn Forte 			stmf_session_lu_unmapall((stmf_lu_t *)req->svc_obj);
7672fcf3ce44SJohn Forte 			/* Kill all the pending I/Os for this LU */
7673fcf3ce44SJohn Forte 			mutex_exit(&stmf_state.stmf_lock);
7674fcf3ce44SJohn Forte 			stmf_task_lu_killall((stmf_lu_t *)req->svc_obj, NULL,
7675fcf3ce44SJohn Forte 			    STMF_ABORTED);
76766ac72a9cSAlexander Stetsenko 			lu = (stmf_lu_t *)req->svc_obj;
76776ac72a9cSAlexander Stetsenko 			ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7678a49dc893SSaso Kiselkov 			stmf_wait_ilu_tasks_finish(ilu);
76796ac72a9cSAlexander Stetsenko 			lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
7680fcf3ce44SJohn Forte 			break;
7681fcf3ce44SJohn Forte 		default:
7682fcf3ce44SJohn Forte 			cmn_err(CE_PANIC, "stmf_svc: unknown cmd %d",
7683fcf3ce44SJohn Forte 			    req->svc_cmd);
7684fcf3ce44SJohn Forte 		}
7685fcf3ce44SJohn Forte 
768609409df0SJeff Biseda 		kmem_free(req, req->svc_req_alloc_size);
7687fcf3ce44SJohn Forte 		mutex_enter(&stmf_state.stmf_lock);
76886ac72a9cSAlexander Stetsenko 	}
76896ac72a9cSAlexander Stetsenko 
76906ac72a9cSAlexander Stetsenko 	stmf_state.stmf_svc_flags &= ~(STMF_SVC_STARTED | STMF_SVC_ACTIVE);
76916ac72a9cSAlexander Stetsenko 	mutex_exit(&stmf_state.stmf_lock);
76926ac72a9cSAlexander Stetsenko }
76936ac72a9cSAlexander Stetsenko 
76946ac72a9cSAlexander Stetsenko static void
stmf_svc_timeout(struct stmf_svc_clocks * clks)7695042f029eSAlexander Stetsenko stmf_svc_timeout(struct stmf_svc_clocks *clks)
76966ac72a9cSAlexander Stetsenko {
76976ac72a9cSAlexander Stetsenko 	clock_t td;
76986ac72a9cSAlexander Stetsenko 	stmf_i_local_port_t *ilport, *next_ilport;
76996ac72a9cSAlexander Stetsenko 	stmf_i_scsi_session_t *iss;
77006ac72a9cSAlexander Stetsenko 
77016ac72a9cSAlexander Stetsenko 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
77026ac72a9cSAlexander Stetsenko 
77036ac72a9cSAlexander Stetsenko 	td = drv_usectohz(20000);
77046ac72a9cSAlexander Stetsenko 
7705fcf3ce44SJohn Forte 	/* Do timeouts */
7706fcf3ce44SJohn Forte 	if (stmf_state.stmf_nlus &&
7707042f029eSAlexander Stetsenko 	    ((!clks->timing_next) || (ddi_get_lbolt() >= clks->timing_next))) {
7708fcf3ce44SJohn Forte 		if (!stmf_state.stmf_svc_ilu_timing) {
7709fcf3ce44SJohn Forte 			/* we are starting a new round */
7710fcf3ce44SJohn Forte 			stmf_state.stmf_svc_ilu_timing =
7711fcf3ce44SJohn Forte 			    stmf_state.stmf_ilulist;
7712042f029eSAlexander Stetsenko 			clks->timing_start = ddi_get_lbolt();
7713fcf3ce44SJohn Forte 		}
77146ac72a9cSAlexander Stetsenko 
7715fcf3ce44SJohn Forte 		stmf_check_ilu_timing();
7716fcf3ce44SJohn Forte 		if (!stmf_state.stmf_svc_ilu_timing) {
7717fcf3ce44SJohn Forte 			/* we finished a complete round */
7718042f029eSAlexander Stetsenko 			clks->timing_next =
7719042f029eSAlexander Stetsenko 			    clks->timing_start + drv_usectohz(5*1000*1000);
7720fcf3ce44SJohn Forte 		} else {
7721fcf3ce44SJohn Forte 			/* we still have some ilu items to check */
7722042f029eSAlexander Stetsenko 			clks->timing_next =
7723fcf3ce44SJohn Forte 			    ddi_get_lbolt() + drv_usectohz(1*1000*1000);
7724fcf3ce44SJohn Forte 		}
77256ac72a9cSAlexander Stetsenko 
772661dfa509SRick McNeal 		if (!list_is_empty(&stmf_state.stmf_svc_list))
77276ac72a9cSAlexander Stetsenko 			return;
7728fcf3ce44SJohn Forte 	}
77296ac72a9cSAlexander Stetsenko 
7730fcf3ce44SJohn Forte 	/* Check if there are free tasks to clear */
7731fcf3ce44SJohn Forte 	if (stmf_state.stmf_nlus &&
7732042f029eSAlexander Stetsenko 	    ((!clks->drain_next) || (ddi_get_lbolt() >= clks->drain_next))) {
7733fcf3ce44SJohn Forte 		if (!stmf_state.stmf_svc_ilu_draining) {
7734fcf3ce44SJohn Forte 			/* we are starting a new round */
7735fcf3ce44SJohn Forte 			stmf_state.stmf_svc_ilu_draining =
7736fcf3ce44SJohn Forte 			    stmf_state.stmf_ilulist;
7737042f029eSAlexander Stetsenko 			clks->drain_start = ddi_get_lbolt();
7738fcf3ce44SJohn Forte 		}
77396ac72a9cSAlexander Stetsenko 
7740fcf3ce44SJohn Forte 		stmf_check_freetask();
7741fcf3ce44SJohn Forte 		if (!stmf_state.stmf_svc_ilu_draining) {
7742fcf3ce44SJohn Forte 			/* we finished a complete round */
7743042f029eSAlexander Stetsenko 			clks->drain_next =
7744042f029eSAlexander Stetsenko 			    clks->drain_start + drv_usectohz(10*1000*1000);
7745fcf3ce44SJohn Forte 		} else {
7746fcf3ce44SJohn Forte 			/* we still have some ilu items to check */
7747042f029eSAlexander Stetsenko 			clks->drain_next =
7748fcf3ce44SJohn Forte 			    ddi_get_lbolt() + drv_usectohz(1*1000*1000);
7749fcf3ce44SJohn Forte 		}
77506ac72a9cSAlexander Stetsenko 
775161dfa509SRick McNeal 		if (!list_is_empty(&stmf_state.stmf_svc_list))
77526ac72a9cSAlexander Stetsenko 			return;
7753fcf3ce44SJohn Forte 	}
7754fcf3ce44SJohn Forte 
7755fcf3ce44SJohn Forte 	/* Check if any active session got its 1st LUN */
7756fcf3ce44SJohn Forte 	if (stmf_state.stmf_process_initial_luns) {
7757fcf3ce44SJohn Forte 		int stmf_level = 0;
7758fcf3ce44SJohn Forte 		int port_level;
77596ac72a9cSAlexander Stetsenko 
7760fcf3ce44SJohn Forte 		for (ilport = stmf_state.stmf_ilportlist; ilport;
7761fcf3ce44SJohn Forte 		    ilport = next_ilport) {
776207377e5eSJohn Forte 			int ilport_lock_held;
7763fcf3ce44SJohn Forte 			next_ilport = ilport->ilport_next;
77646ac72a9cSAlexander Stetsenko 
7765fcf3ce44SJohn Forte 			if ((ilport->ilport_flags &
77666ac72a9cSAlexander Stetsenko 			    ILPORT_SS_GOT_INITIAL_LUNS) == 0)
7767fcf3ce44SJohn Forte 				continue;
77686ac72a9cSAlexander Stetsenko 
7769fcf3ce44SJohn Forte 			port_level = 0;
7770fcf3ce44SJohn Forte 			rw_enter(&ilport->ilport_lock, RW_READER);
777107377e5eSJohn Forte 			ilport_lock_held = 1;
77726ac72a9cSAlexander Stetsenko 
7773fcf3ce44SJohn Forte 			for (iss = ilport->ilport_ss_list; iss;
7774fcf3ce44SJohn Forte 			    iss = iss->iss_next) {
7775fcf3ce44SJohn Forte 				if ((iss->iss_flags &
77766ac72a9cSAlexander Stetsenko 				    ISS_GOT_INITIAL_LUNS) == 0)
7777fcf3ce44SJohn Forte 					continue;
77786ac72a9cSAlexander Stetsenko 
7779fcf3ce44SJohn Forte 				port_level++;
7780fcf3ce44SJohn Forte 				stmf_level++;
7781fcf3ce44SJohn Forte 				atomic_and_32(&iss->iss_flags,
7782fcf3ce44SJohn Forte 				    ~ISS_GOT_INITIAL_LUNS);
7783fcf3ce44SJohn Forte 				atomic_or_32(&iss->iss_flags,
7784fcf3ce44SJohn Forte 				    ISS_EVENT_ACTIVE);
7785fcf3ce44SJohn Forte 				rw_exit(&ilport->ilport_lock);
778607377e5eSJohn Forte 				ilport_lock_held = 0;
7787fcf3ce44SJohn Forte 				mutex_exit(&stmf_state.stmf_lock);
7788fcf3ce44SJohn Forte 				stmf_generate_lport_event(ilport,
7789fcf3ce44SJohn Forte 				    LPORT_EVENT_INITIAL_LUN_MAPPED,
7790fcf3ce44SJohn Forte 				    iss->iss_ss, 0);
7791fcf3ce44SJohn Forte 				atomic_and_32(&iss->iss_flags,
7792fcf3ce44SJohn Forte 				    ~ISS_EVENT_ACTIVE);
7793fcf3ce44SJohn Forte 				mutex_enter(&stmf_state.stmf_lock);
7794fcf3ce44SJohn Forte 				/*
7795fcf3ce44SJohn Forte 				 * scan all the ilports again as the
7796fcf3ce44SJohn Forte 				 * ilport list might have changed.
7797fcf3ce44SJohn Forte 				 */
77986ac72a9cSAlexander Stetsenko 				next_ilport = stmf_state.stmf_ilportlist;
7799fcf3ce44SJohn Forte 				break;
7800fcf3ce44SJohn Forte 			}
78016ac72a9cSAlexander Stetsenko 
78026ac72a9cSAlexander Stetsenko 			if (port_level == 0)
7803fcf3ce44SJohn Forte 				atomic_and_32(&ilport->ilport_flags,
7804fcf3ce44SJohn Forte 				    ~ILPORT_SS_GOT_INITIAL_LUNS);
7805fcf3ce44SJohn Forte 			/* drop the lock if we are holding it. */
780607377e5eSJohn Forte 			if (ilport_lock_held == 1)
7807fcf3ce44SJohn Forte 				rw_exit(&ilport->ilport_lock);
7808fcf3ce44SJohn Forte 
7809fcf3ce44SJohn Forte 			/* Max 4 session at a time */
78106ac72a9cSAlexander Stetsenko 			if (stmf_level >= 4)
7811fcf3ce44SJohn Forte 				break;
7812fcf3ce44SJohn Forte 		}
78136ac72a9cSAlexander Stetsenko 
78146ac72a9cSAlexander Stetsenko 		if (stmf_level == 0)
7815fcf3ce44SJohn Forte 			stmf_state.stmf_process_initial_luns = 0;
7816fcf3ce44SJohn Forte 	}
7817fcf3ce44SJohn Forte 
7818fcf3ce44SJohn Forte 	stmf_state.stmf_svc_flags &= ~STMF_SVC_ACTIVE;
7819d3d50737SRafael Vanoni 	(void) cv_reltimedwait(&stmf_state.stmf_cv,
7820d3d50737SRafael Vanoni 	    &stmf_state.stmf_lock, td, TR_CLOCK_TICK);
7821fcf3ce44SJohn Forte 	stmf_state.stmf_svc_flags |= STMF_SVC_ACTIVE;
7822fcf3ce44SJohn Forte }
7823fcf3ce44SJohn Forte 
7824a49dc893SSaso Kiselkov /*
7825a49dc893SSaso Kiselkov  * Waits for ongoing I/O tasks to finish on an LU in preparation for
7826a49dc893SSaso Kiselkov  * the LU's offlining. The LU should already be in an Offlining state
7827a49dc893SSaso Kiselkov  * (otherwise I/O to the LU might never end). There is an additional
7828a49dc893SSaso Kiselkov  * enforcement of this via a deadman timer check.
7829a49dc893SSaso Kiselkov  */
7830a49dc893SSaso Kiselkov static void
stmf_wait_ilu_tasks_finish(stmf_i_lu_t * ilu)7831a49dc893SSaso Kiselkov stmf_wait_ilu_tasks_finish(stmf_i_lu_t *ilu)
7832a49dc893SSaso Kiselkov {
7833a49dc893SSaso Kiselkov 	clock_t start, now, deadline;
7834a49dc893SSaso Kiselkov 
7835a49dc893SSaso Kiselkov 	start = now = ddi_get_lbolt();
7836a49dc893SSaso Kiselkov 	deadline = start + drv_usectohz(stmf_io_deadman * 1000000llu);
7837a49dc893SSaso Kiselkov 	mutex_enter(&ilu->ilu_task_lock);
7838a49dc893SSaso Kiselkov 	while (ilu->ilu_ntasks != ilu->ilu_ntasks_free) {
7839a49dc893SSaso Kiselkov 		(void) cv_timedwait(&ilu->ilu_offline_pending_cv,
7840a49dc893SSaso Kiselkov 		    &ilu->ilu_task_lock, deadline);
7841a49dc893SSaso Kiselkov 		now = ddi_get_lbolt();
7842a49dc893SSaso Kiselkov 		if (now > deadline) {
7843a49dc893SSaso Kiselkov 			if (stmf_io_deadman_enabled) {
7844a49dc893SSaso Kiselkov 				cmn_err(CE_PANIC, "stmf_svc: I/O deadman hit "
7845a49dc893SSaso Kiselkov 				    "on STMF_CMD_LU_OFFLINE after %d seconds",
7846a49dc893SSaso Kiselkov 				    stmf_io_deadman);
7847a49dc893SSaso Kiselkov 			} else {
7848a49dc893SSaso Kiselkov 				/* keep on spinning */
7849a49dc893SSaso Kiselkov 				deadline = now + drv_usectohz(stmf_io_deadman *
7850a49dc893SSaso Kiselkov 				    1000000llu);
7851a49dc893SSaso Kiselkov 			}
7852a49dc893SSaso Kiselkov 		}
7853a49dc893SSaso Kiselkov 	}
7854a49dc893SSaso Kiselkov 	mutex_exit(&ilu->ilu_task_lock);
7855a49dc893SSaso Kiselkov 	DTRACE_PROBE1(deadman__timeout__wait, clock_t, now - start);
7856a49dc893SSaso Kiselkov }
7857a49dc893SSaso Kiselkov 
7858fcf3ce44SJohn Forte void
stmf_svc_queue(int cmd,void * obj,stmf_state_change_info_t * info)7859fcf3ce44SJohn Forte stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info)
7860fcf3ce44SJohn Forte {
7861fcf3ce44SJohn Forte 	stmf_svc_req_t *req;
7862fcf3ce44SJohn Forte 	int s;
7863fcf3ce44SJohn Forte 
7864fcf3ce44SJohn Forte 	ASSERT(!mutex_owned(&stmf_state.stmf_lock));
7865fcf3ce44SJohn Forte 	s = sizeof (stmf_svc_req_t);
7866fcf3ce44SJohn Forte 	if (info->st_additional_info) {
7867fcf3ce44SJohn Forte 		s += strlen(info->st_additional_info) + 1;
7868fcf3ce44SJohn Forte 	}
7869fcf3ce44SJohn Forte 	req = kmem_zalloc(s, KM_SLEEP);
7870fcf3ce44SJohn Forte 
7871fcf3ce44SJohn Forte 	req->svc_cmd = cmd;
7872fcf3ce44SJohn Forte 	req->svc_obj = obj;
7873fcf3ce44SJohn Forte 	req->svc_info.st_rflags = info->st_rflags;
7874fcf3ce44SJohn Forte 	if (info->st_additional_info) {
7875fcf3ce44SJohn Forte 		req->svc_info.st_additional_info = (char *)(GET_BYTE_OFFSET(req,
7876fcf3ce44SJohn Forte 		    sizeof (stmf_svc_req_t)));
7877fcf3ce44SJohn Forte 		(void) strcpy(req->svc_info.st_additional_info,
7878fcf3ce44SJohn Forte 		    info->st_additional_info);
7879fcf3ce44SJohn Forte 	}
7880fcf3ce44SJohn Forte 	req->svc_req_alloc_size = s;
7881fcf3ce44SJohn Forte 
7882fcf3ce44SJohn Forte 	mutex_enter(&stmf_state.stmf_lock);
788361dfa509SRick McNeal 	list_insert_tail(&stmf_state.stmf_svc_list, req);
7884fcf3ce44SJohn Forte 	if ((stmf_state.stmf_svc_flags & STMF_SVC_ACTIVE) == 0) {
7885fcf3ce44SJohn Forte 		cv_signal(&stmf_state.stmf_cv);
7886fcf3ce44SJohn Forte 	}
7887fcf3ce44SJohn Forte 	mutex_exit(&stmf_state.stmf_lock);
7888fcf3ce44SJohn Forte }
7889fcf3ce44SJohn Forte 
78906ac72a9cSAlexander Stetsenko static void
stmf_svc_kill_obj_requests(void * obj)78916ac72a9cSAlexander Stetsenko stmf_svc_kill_obj_requests(void *obj)
78926ac72a9cSAlexander Stetsenko {
78936ac72a9cSAlexander Stetsenko 	stmf_svc_req_t *req;
78946ac72a9cSAlexander Stetsenko 
78956ac72a9cSAlexander Stetsenko 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
78966ac72a9cSAlexander Stetsenko 
789761dfa509SRick McNeal 	for (req = list_head(&stmf_state.stmf_svc_list); req != NULL;
789861dfa509SRick McNeal 	    req = list_next(&stmf_state.stmf_svc_list, req)) {
78996ac72a9cSAlexander Stetsenko 		if (req->svc_obj == obj) {
790061dfa509SRick McNeal 			list_remove(&stmf_state.stmf_svc_list, req);
79016ac72a9cSAlexander Stetsenko 			kmem_free(req, req->svc_req_alloc_size);
79026ac72a9cSAlexander Stetsenko 		}
79036ac72a9cSAlexander Stetsenko 	}
79046ac72a9cSAlexander Stetsenko }
79056ac72a9cSAlexander Stetsenko 
7906fcf3ce44SJohn Forte void
stmf_trace(caddr_t ident,const char * fmt,...)7907fcf3ce44SJohn Forte stmf_trace(caddr_t ident, const char *fmt, ...)
7908fcf3ce44SJohn Forte {
7909fcf3ce44SJohn Forte 	va_list args;
7910fcf3ce44SJohn Forte 	char tbuf[160];
7911fcf3ce44SJohn Forte 	int len;
7912fcf3ce44SJohn Forte 
7913fcf3ce44SJohn Forte 	if (!stmf_trace_on)
7914fcf3ce44SJohn Forte 		return;
7915fcf3ce44SJohn Forte 	len = snprintf(tbuf, 158, "%s:%07lu: ", ident ? ident : "",
7916fcf3ce44SJohn Forte 	    ddi_get_lbolt());
7917fcf3ce44SJohn Forte 	va_start(args, fmt);
7918fcf3ce44SJohn Forte 	len += vsnprintf(tbuf + len, 158 - len, fmt, args);
7919fcf3ce44SJohn Forte 	va_end(args);
7920fcf3ce44SJohn Forte 
7921fcf3ce44SJohn Forte 	if (len > 158) {
7922fcf3ce44SJohn Forte 		len = 158;
7923fcf3ce44SJohn Forte 	}
7924fcf3ce44SJohn Forte 	tbuf[len++] = '\n';
7925bad5e468SToomas Soome 	tbuf[len] = '\0';
7926fcf3ce44SJohn Forte 
7927fcf3ce44SJohn Forte 	mutex_enter(&trace_buf_lock);
7928fcf3ce44SJohn Forte 	bcopy(tbuf, &stmf_trace_buf[trace_buf_curndx], len+1);
7929fcf3ce44SJohn Forte 	trace_buf_curndx += len;
7930fcf3ce44SJohn Forte 	if (trace_buf_curndx > (trace_buf_size - 320))
7931fcf3ce44SJohn Forte 		trace_buf_curndx = 0;
7932fcf3ce44SJohn Forte 	mutex_exit(&trace_buf_lock);
7933fcf3ce44SJohn Forte }
7934fcf3ce44SJohn Forte 
7935fcf3ce44SJohn Forte void
stmf_trace_clear()7936fcf3ce44SJohn Forte stmf_trace_clear()
7937fcf3ce44SJohn Forte {
7938fcf3ce44SJohn Forte 	if (!stmf_trace_on)
7939fcf3ce44SJohn Forte 		return;
7940fcf3ce44SJohn Forte 	mutex_enter(&trace_buf_lock);
7941fcf3ce44SJohn Forte 	trace_buf_curndx = 0;
7942fcf3ce44SJohn Forte 	if (trace_buf_size > 0)
7943bad5e468SToomas Soome 		stmf_trace_buf[0] = '\0';
7944fcf3ce44SJohn Forte 	mutex_exit(&trace_buf_lock);
7945fcf3ce44SJohn Forte }
7946fcf3ce44SJohn Forte 
794761dfa509SRick McNeal /*
794861dfa509SRick McNeal  * NOTE: Due to lock order problems that are not possible to fix this
794961dfa509SRick McNeal  * method drops and reacquires the itask_mutex around the call to stmf_ctl.
795061dfa509SRick McNeal  * Another possible work around would be to use a dispatch queue and have
795161dfa509SRick McNeal  * the call to stmf_ctl run on another thread that's not holding the
795261dfa509SRick McNeal  * itask_mutex. The problem with that approach is that it's difficult to
795361dfa509SRick McNeal  * determine what impact an asynchronous change would have on the system state.
795461dfa509SRick McNeal  */
7955fcf3ce44SJohn Forte static void
stmf_abort_task_offline(scsi_task_t * task,int offline_lu,char * info)7956fcf3ce44SJohn Forte stmf_abort_task_offline(scsi_task_t *task, int offline_lu, char *info)
7957fcf3ce44SJohn Forte {
7958fcf3ce44SJohn Forte 	stmf_state_change_info_t	change_info;
7959fcf3ce44SJohn Forte 	void				*ctl_private;
7960fcf3ce44SJohn Forte 	uint32_t			ctl_cmd;
7961fcf3ce44SJohn Forte 	int				msg = 0;
796261dfa509SRick McNeal 	stmf_i_scsi_task_t		*itask =
796361dfa509SRick McNeal 	    (stmf_i_scsi_task_t *)task->task_stmf_private;
7964fcf3ce44SJohn Forte 
7965fcf3ce44SJohn Forte 	stmf_trace("FROM STMF", "abort_task_offline called for %s: %s",
7966fcf3ce44SJohn Forte 	    offline_lu ? "LU" : "LPORT", info ? info : "no additional info");
7967fcf3ce44SJohn Forte 	change_info.st_additional_info = info;
796861dfa509SRick McNeal 	ASSERT(mutex_owned(&itask->itask_mutex));
796961dfa509SRick McNeal 
7970fcf3ce44SJohn Forte 	if (offline_lu) {
7971fcf3ce44SJohn Forte 		change_info.st_rflags = STMF_RFLAG_RESET |
7972fcf3ce44SJohn Forte 		    STMF_RFLAG_LU_ABORT;
7973fcf3ce44SJohn Forte 		ctl_private = task->task_lu;
7974fcf3ce44SJohn Forte 		if (((stmf_i_lu_t *)
7975fcf3ce44SJohn Forte 		    task->task_lu->lu_stmf_private)->ilu_state ==
7976fcf3ce44SJohn Forte 		    STMF_STATE_ONLINE) {
7977fcf3ce44SJohn Forte 			msg = 1;
7978fcf3ce44SJohn Forte 		}
7979fcf3ce44SJohn Forte 		ctl_cmd = STMF_CMD_LU_OFFLINE;
7980fcf3ce44SJohn Forte 	} else {
7981fcf3ce44SJohn Forte 		change_info.st_rflags = STMF_RFLAG_RESET |
7982fcf3ce44SJohn Forte 		    STMF_RFLAG_LPORT_ABORT;
7983fcf3ce44SJohn Forte 		ctl_private = task->task_lport;
7984fcf3ce44SJohn Forte 		if (((stmf_i_local_port_t *)
7985fcf3ce44SJohn Forte 		    task->task_lport->lport_stmf_private)->ilport_state ==
7986fcf3ce44SJohn Forte 		    STMF_STATE_ONLINE) {
7987fcf3ce44SJohn Forte 			msg = 1;
7988fcf3ce44SJohn Forte 		}
7989fcf3ce44SJohn Forte 		ctl_cmd = STMF_CMD_LPORT_OFFLINE;
7990fcf3ce44SJohn Forte 	}
7991fcf3ce44SJohn Forte 
7992fcf3ce44SJohn Forte 	if (msg) {
7993fcf3ce44SJohn Forte 		stmf_trace(0, "Calling stmf_ctl to offline %s : %s",
7994fcf3ce44SJohn Forte 		    offline_lu ? "LU" : "LPORT", info ? info :
7995fcf3ce44SJohn Forte 		    "<no additional info>");
7996fcf3ce44SJohn Forte 	}
799761dfa509SRick McNeal 	mutex_exit(&itask->itask_mutex);
7998fcf3ce44SJohn Forte 	(void) stmf_ctl(ctl_cmd, ctl_private, &change_info);
799961dfa509SRick McNeal 	mutex_enter(&itask->itask_mutex);
8000fcf3ce44SJohn Forte }
8001716c1805SNattuvetty Bhavyan 
8002716c1805SNattuvetty Bhavyan static char
stmf_ctoi(char c)8003716c1805SNattuvetty Bhavyan stmf_ctoi(char c)
8004716c1805SNattuvetty Bhavyan {
8005716c1805SNattuvetty Bhavyan 	if ((c >= '0') && (c <= '9'))
8006716c1805SNattuvetty Bhavyan 		c -= '0';
8007716c1805SNattuvetty Bhavyan 	else if ((c >= 'A') && (c <= 'F'))
8008716c1805SNattuvetty Bhavyan 		c = c - 'A' + 10;
8009716c1805SNattuvetty Bhavyan 	else if ((c >= 'a') && (c <= 'f'))
8010716c1805SNattuvetty Bhavyan 		c = c - 'a' + 10;
8011716c1805SNattuvetty Bhavyan 	else
8012716c1805SNattuvetty Bhavyan 		c = -1;
8013716c1805SNattuvetty Bhavyan 	return (c);
8014716c1805SNattuvetty Bhavyan }
8015716c1805SNattuvetty Bhavyan 
8016716c1805SNattuvetty Bhavyan /* Convert from Hex value in ASCII format to the equivalent bytes */
8017716c1805SNattuvetty Bhavyan static boolean_t
stmf_base16_str_to_binary(char * c,int dplen,uint8_t * dp)8018716c1805SNattuvetty Bhavyan stmf_base16_str_to_binary(char *c, int dplen, uint8_t *dp)
8019716c1805SNattuvetty Bhavyan {
8020716c1805SNattuvetty Bhavyan 	int		ii;
8021716c1805SNattuvetty Bhavyan 
8022716c1805SNattuvetty Bhavyan 	for (ii = 0; ii < dplen; ii++) {
8023716c1805SNattuvetty Bhavyan 		char nibble1, nibble2;
8024716c1805SNattuvetty Bhavyan 		char enc_char = *c++;
8025716c1805SNattuvetty Bhavyan 		nibble1 = stmf_ctoi(enc_char);
8026716c1805SNattuvetty Bhavyan 
8027716c1805SNattuvetty Bhavyan 		enc_char = *c++;
8028716c1805SNattuvetty Bhavyan 		nibble2 = stmf_ctoi(enc_char);
8029716c1805SNattuvetty Bhavyan 		if (nibble1 == -1 || nibble2 == -1)
8030716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8031716c1805SNattuvetty Bhavyan 
8032716c1805SNattuvetty Bhavyan 		dp[ii] = (nibble1 << 4) | nibble2;
8033716c1805SNattuvetty Bhavyan 	}
8034716c1805SNattuvetty Bhavyan 	return (B_TRUE);
8035716c1805SNattuvetty Bhavyan }
8036716c1805SNattuvetty Bhavyan 
8037716c1805SNattuvetty Bhavyan boolean_t
stmf_scsilib_tptid_validate(scsi_transport_id_t * tptid,uint32_t total_sz,uint16_t * tptid_sz)8038716c1805SNattuvetty Bhavyan stmf_scsilib_tptid_validate(scsi_transport_id_t *tptid, uint32_t total_sz,
8039716c1805SNattuvetty Bhavyan     uint16_t *tptid_sz)
8040716c1805SNattuvetty Bhavyan {
8041716c1805SNattuvetty Bhavyan 	uint16_t tpd_len = SCSI_TPTID_SIZE;
8042716c1805SNattuvetty Bhavyan 
8043716c1805SNattuvetty Bhavyan 	if (tptid_sz)
8044716c1805SNattuvetty Bhavyan 		*tptid_sz = 0;
8045716c1805SNattuvetty Bhavyan 	if (total_sz < sizeof (scsi_transport_id_t))
8046716c1805SNattuvetty Bhavyan 		return (B_FALSE);
8047716c1805SNattuvetty Bhavyan 
8048716c1805SNattuvetty Bhavyan 	switch (tptid->protocol_id) {
8049716c1805SNattuvetty Bhavyan 
8050716c1805SNattuvetty Bhavyan 	case PROTOCOL_FIBRE_CHANNEL:
8051716c1805SNattuvetty Bhavyan 		/* FC Transport ID validation checks. SPC3 rev23, Table 284 */
8052716c1805SNattuvetty Bhavyan 		if (total_sz < tpd_len || tptid->format_code != 0)
8053716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8054716c1805SNattuvetty Bhavyan 		break;
8055716c1805SNattuvetty Bhavyan 
805661dfa509SRick McNeal 	case PROTOCOL_iSCSI: /* CSTYLED */
8057716c1805SNattuvetty Bhavyan 		{
8058716c1805SNattuvetty Bhavyan 		iscsi_transport_id_t	*iscsiid;
8059716c1805SNattuvetty Bhavyan 		uint16_t		adn_len, name_len;
8060716c1805SNattuvetty Bhavyan 
8061716c1805SNattuvetty Bhavyan 		/* Check for valid format code, SPC3 rev 23 Table 288 */
8062716c1805SNattuvetty Bhavyan 		if ((total_sz < tpd_len) ||
8063716c1805SNattuvetty Bhavyan 		    (tptid->format_code != 0 && tptid->format_code != 1))
8064716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8065716c1805SNattuvetty Bhavyan 
8066716c1805SNattuvetty Bhavyan 		iscsiid = (iscsi_transport_id_t *)tptid;
8067716c1805SNattuvetty Bhavyan 		adn_len = READ_SCSI16(iscsiid->add_len, uint16_t);
8068716c1805SNattuvetty Bhavyan 		tpd_len = sizeof (iscsi_transport_id_t) + adn_len - 1;
8069716c1805SNattuvetty Bhavyan 
8070716c1805SNattuvetty Bhavyan 		/*
8071716c1805SNattuvetty Bhavyan 		 * iSCSI Transport ID validation checks.
8072716c1805SNattuvetty Bhavyan 		 * As per SPC3 rev 23 Section 7.5.4.6 and Table 289 & Table 290
8073716c1805SNattuvetty Bhavyan 		 */
8074716c1805SNattuvetty Bhavyan 		if (adn_len < 20 || (adn_len % 4 != 0))
8075716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8076716c1805SNattuvetty Bhavyan 
8077716c1805SNattuvetty Bhavyan 		name_len = strnlen(iscsiid->iscsi_name, adn_len);
8078716c1805SNattuvetty Bhavyan 		if (name_len == 0 || name_len >= adn_len)
8079716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8080716c1805SNattuvetty Bhavyan 
8081716c1805SNattuvetty Bhavyan 		/* If the format_code is 1 check for ISID seperator */
8082716c1805SNattuvetty Bhavyan 		if ((tptid->format_code == 1) && (strstr(iscsiid->iscsi_name,
8083716c1805SNattuvetty Bhavyan 		    SCSI_TPTID_ISCSI_ISID_SEPERATOR) == NULL))
8084716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8085716c1805SNattuvetty Bhavyan 
8086716c1805SNattuvetty Bhavyan 		}
8087716c1805SNattuvetty Bhavyan 		break;
8088716c1805SNattuvetty Bhavyan 
8089716c1805SNattuvetty Bhavyan 	case PROTOCOL_SRP:
8090716c1805SNattuvetty Bhavyan 		/* SRP Transport ID validation checks. SPC3 rev23, Table 287 */
8091716c1805SNattuvetty Bhavyan 		if (total_sz < tpd_len || tptid->format_code != 0)
8092716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8093716c1805SNattuvetty Bhavyan 		break;
8094716c1805SNattuvetty Bhavyan 
8095716c1805SNattuvetty Bhavyan 	case PROTOCOL_PARALLEL_SCSI:
8096716c1805SNattuvetty Bhavyan 	case PROTOCOL_SSA:
8097716c1805SNattuvetty Bhavyan 	case PROTOCOL_IEEE_1394:
8098716c1805SNattuvetty Bhavyan 	case PROTOCOL_SAS:
8099716c1805SNattuvetty Bhavyan 	case PROTOCOL_ADT:
8100716c1805SNattuvetty Bhavyan 	case PROTOCOL_ATAPI:
810161dfa509SRick McNeal 	default: /* CSTYLED */
8102716c1805SNattuvetty Bhavyan 		{
8103716c1805SNattuvetty Bhavyan 		stmf_dflt_scsi_tptid_t *dflttpd;
8104716c1805SNattuvetty Bhavyan 
8105716c1805SNattuvetty Bhavyan 		tpd_len = sizeof (stmf_dflt_scsi_tptid_t);
8106716c1805SNattuvetty Bhavyan 		if (total_sz < tpd_len)
8107716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8108716c1805SNattuvetty Bhavyan 		dflttpd = (stmf_dflt_scsi_tptid_t *)tptid;
8109716c1805SNattuvetty Bhavyan 		tpd_len = tpd_len + SCSI_READ16(&dflttpd->ident_len) - 1;
8110716c1805SNattuvetty Bhavyan 		if (total_sz < tpd_len)
8111716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8112716c1805SNattuvetty Bhavyan 		}
8113716c1805SNattuvetty Bhavyan 		break;
8114716c1805SNattuvetty Bhavyan 	}
8115716c1805SNattuvetty Bhavyan 	if (tptid_sz)
8116716c1805SNattuvetty Bhavyan 		*tptid_sz = tpd_len;
8117716c1805SNattuvetty Bhavyan 	return (B_TRUE);
8118716c1805SNattuvetty Bhavyan }
8119716c1805SNattuvetty Bhavyan 
8120716c1805SNattuvetty Bhavyan boolean_t
stmf_scsilib_tptid_compare(scsi_transport_id_t * tpd1,scsi_transport_id_t * tpd2)8121bad5e468SToomas Soome stmf_scsilib_tptid_compare(scsi_transport_id_t *tpd1, scsi_transport_id_t *tpd2)
8122716c1805SNattuvetty Bhavyan {
8123716c1805SNattuvetty Bhavyan 	if ((tpd1->protocol_id != tpd2->protocol_id) ||
8124716c1805SNattuvetty Bhavyan 	    (tpd1->format_code != tpd2->format_code))
8125716c1805SNattuvetty Bhavyan 		return (B_FALSE);
8126716c1805SNattuvetty Bhavyan 
8127716c1805SNattuvetty Bhavyan 	switch (tpd1->protocol_id) {
8128716c1805SNattuvetty Bhavyan 
812961dfa509SRick McNeal 	case PROTOCOL_iSCSI: /* CSTYLED */
8130716c1805SNattuvetty Bhavyan 		{
8131716c1805SNattuvetty Bhavyan 		iscsi_transport_id_t *iscsitpd1, *iscsitpd2;
8132716c1805SNattuvetty Bhavyan 		uint16_t len;
8133716c1805SNattuvetty Bhavyan 
8134716c1805SNattuvetty Bhavyan 		iscsitpd1 = (iscsi_transport_id_t *)tpd1;
8135716c1805SNattuvetty Bhavyan 		iscsitpd2 = (iscsi_transport_id_t *)tpd2;
8136716c1805SNattuvetty Bhavyan 		len = SCSI_READ16(&iscsitpd1->add_len);
8137716c1805SNattuvetty Bhavyan 		if ((memcmp(iscsitpd1->add_len, iscsitpd2->add_len, 2) != 0) ||
8138716c1805SNattuvetty Bhavyan 		    (memcmp(iscsitpd1->iscsi_name, iscsitpd2->iscsi_name, len)
8139716c1805SNattuvetty Bhavyan 		    != 0))
8140716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8141716c1805SNattuvetty Bhavyan 		}
8142716c1805SNattuvetty Bhavyan 		break;
8143716c1805SNattuvetty Bhavyan 
814461dfa509SRick McNeal 	case PROTOCOL_SRP: /* CSTYLED */
8145716c1805SNattuvetty Bhavyan 		{
8146716c1805SNattuvetty Bhavyan 		scsi_srp_transport_id_t *srptpd1, *srptpd2;
8147716c1805SNattuvetty Bhavyan 
8148716c1805SNattuvetty Bhavyan 		srptpd1 = (scsi_srp_transport_id_t *)tpd1;
8149716c1805SNattuvetty Bhavyan 		srptpd2 = (scsi_srp_transport_id_t *)tpd2;
8150716c1805SNattuvetty Bhavyan 		if (memcmp(srptpd1->srp_name, srptpd2->srp_name,
8151716c1805SNattuvetty Bhavyan 		    sizeof (srptpd1->srp_name)) != 0)
8152716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8153716c1805SNattuvetty Bhavyan 		}
8154716c1805SNattuvetty Bhavyan 		break;
8155716c1805SNattuvetty Bhavyan 
815661dfa509SRick McNeal 	case PROTOCOL_FIBRE_CHANNEL: /* CSTYLED */
8157716c1805SNattuvetty Bhavyan 		{
8158716c1805SNattuvetty Bhavyan 		scsi_fc_transport_id_t *fctpd1, *fctpd2;
8159716c1805SNattuvetty Bhavyan 
8160716c1805SNattuvetty Bhavyan 		fctpd1 = (scsi_fc_transport_id_t *)tpd1;
8161716c1805SNattuvetty Bhavyan 		fctpd2 = (scsi_fc_transport_id_t *)tpd2;
8162716c1805SNattuvetty Bhavyan 		if (memcmp(fctpd1->port_name, fctpd2->port_name,
8163716c1805SNattuvetty Bhavyan 		    sizeof (fctpd1->port_name)) != 0)
8164716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8165716c1805SNattuvetty Bhavyan 		}
8166716c1805SNattuvetty Bhavyan 		break;
8167716c1805SNattuvetty Bhavyan 
8168716c1805SNattuvetty Bhavyan 	case PROTOCOL_PARALLEL_SCSI:
8169716c1805SNattuvetty Bhavyan 	case PROTOCOL_SSA:
8170716c1805SNattuvetty Bhavyan 	case PROTOCOL_IEEE_1394:
8171716c1805SNattuvetty Bhavyan 	case PROTOCOL_SAS:
8172716c1805SNattuvetty Bhavyan 	case PROTOCOL_ADT:
8173716c1805SNattuvetty Bhavyan 	case PROTOCOL_ATAPI:
817461dfa509SRick McNeal 	default: /* CSTYLED */
8175716c1805SNattuvetty Bhavyan 		{
8176716c1805SNattuvetty Bhavyan 		stmf_dflt_scsi_tptid_t *dflt1, *dflt2;
8177716c1805SNattuvetty Bhavyan 		uint16_t len;
8178716c1805SNattuvetty Bhavyan 
8179716c1805SNattuvetty Bhavyan 		dflt1 = (stmf_dflt_scsi_tptid_t *)tpd1;
8180716c1805SNattuvetty Bhavyan 		dflt2 = (stmf_dflt_scsi_tptid_t *)tpd2;
8181716c1805SNattuvetty Bhavyan 		len = SCSI_READ16(&dflt1->ident_len);
8182716c1805SNattuvetty Bhavyan 		if ((memcmp(dflt1->ident_len, dflt2->ident_len, 2) != 0) ||
8183716c1805SNattuvetty Bhavyan 		    (memcmp(dflt1->ident, dflt2->ident, len) != 0))
8184716c1805SNattuvetty Bhavyan 			return (B_FALSE);
8185716c1805SNattuvetty Bhavyan 		}
8186716c1805SNattuvetty Bhavyan 		break;
8187716c1805SNattuvetty Bhavyan 	}
8188716c1805SNattuvetty Bhavyan 	return (B_TRUE);
8189716c1805SNattuvetty Bhavyan }
8190716c1805SNattuvetty Bhavyan 
8191716c1805SNattuvetty Bhavyan /*
8192716c1805SNattuvetty Bhavyan  * Changes devid_desc to corresponding TransportID format
8193716c1805SNattuvetty Bhavyan  * Returns :- pointer to stmf_remote_port_t
8194716c1805SNattuvetty Bhavyan  * Note    :- Allocates continous memory for stmf_remote_port_t and TransportID,
8195716c1805SNattuvetty Bhavyan  *            This memory need to be freed when this remote_port is no longer
8196716c1805SNattuvetty Bhavyan  *            used.
8197716c1805SNattuvetty Bhavyan  */
8198716c1805SNattuvetty Bhavyan stmf_remote_port_t *
stmf_scsilib_devid_to_remote_port(scsi_devid_desc_t * devid)8199716c1805SNattuvetty Bhavyan stmf_scsilib_devid_to_remote_port(scsi_devid_desc_t *devid)
8200716c1805SNattuvetty Bhavyan {
8201716c1805SNattuvetty Bhavyan 	struct scsi_fc_transport_id	*fc_tpd;
8202716c1805SNattuvetty Bhavyan 	struct iscsi_transport_id	*iscsi_tpd;
8203716c1805SNattuvetty Bhavyan 	struct scsi_srp_transport_id	*srp_tpd;
8204716c1805SNattuvetty Bhavyan 	struct stmf_dflt_scsi_tptid	*dflt_tpd;
8205716c1805SNattuvetty Bhavyan 	uint16_t ident_len,  sz = 0;
8206716c1805SNattuvetty Bhavyan 	stmf_remote_port_t *rpt = NULL;
8207716c1805SNattuvetty Bhavyan 
8208716c1805SNattuvetty Bhavyan 	ident_len = devid->ident_length;
8209716c1805SNattuvetty Bhavyan 	ASSERT(ident_len);
8210716c1805SNattuvetty Bhavyan 	switch (devid->protocol_id) {
8211716c1805SNattuvetty Bhavyan 	case PROTOCOL_FIBRE_CHANNEL:
8212716c1805SNattuvetty Bhavyan 		sz = sizeof (scsi_fc_transport_id_t);
8213716c1805SNattuvetty Bhavyan 		rpt = stmf_remote_port_alloc(sz);
8214716c1805SNattuvetty Bhavyan 		rpt->rport_tptid->format_code = 0;
8215716c1805SNattuvetty Bhavyan 		rpt->rport_tptid->protocol_id = devid->protocol_id;
8216716c1805SNattuvetty Bhavyan 		fc_tpd = (scsi_fc_transport_id_t *)rpt->rport_tptid;
8217716c1805SNattuvetty Bhavyan 		/*
8218716c1805SNattuvetty Bhavyan 		 * convert from "wwn.xxxxxxxxxxxxxxxx" to 8-byte binary
8219716c1805SNattuvetty Bhavyan 		 * skip first 4 byte for "wwn."
8220716c1805SNattuvetty Bhavyan 		 */
8221716c1805SNattuvetty Bhavyan 		ASSERT(strncmp("wwn.", (char *)devid->ident, 4) == 0);
8222716c1805SNattuvetty Bhavyan 		if ((ident_len < SCSI_TPTID_FC_PORT_NAME_SIZE * 2 + 4) ||
8223716c1805SNattuvetty Bhavyan 		    !stmf_base16_str_to_binary((char *)devid->ident + 4,
8224716c1805SNattuvetty Bhavyan 		    SCSI_TPTID_FC_PORT_NAME_SIZE, fc_tpd->port_name))
8225716c1805SNattuvetty Bhavyan 			goto devid_to_remote_port_fail;
8226716c1805SNattuvetty Bhavyan 		break;
8227716c1805SNattuvetty Bhavyan 
8228716c1805SNattuvetty Bhavyan 	case PROTOCOL_iSCSI:
8229716c1805SNattuvetty Bhavyan 		sz = ALIGNED_TO_8BYTE_BOUNDARY(sizeof (iscsi_transport_id_t) +
8230716c1805SNattuvetty Bhavyan 		    ident_len - 1);
8231716c1805SNattuvetty Bhavyan 		rpt = stmf_remote_port_alloc(sz);
8232716c1805SNattuvetty Bhavyan 		rpt->rport_tptid->format_code = 0;
8233716c1805SNattuvetty Bhavyan 		rpt->rport_tptid->protocol_id = devid->protocol_id;
8234716c1805SNattuvetty Bhavyan 		iscsi_tpd = (iscsi_transport_id_t *)rpt->rport_tptid;
8235716c1805SNattuvetty Bhavyan 		SCSI_WRITE16(iscsi_tpd->add_len, ident_len);
8236716c1805SNattuvetty Bhavyan 		(void) memcpy(iscsi_tpd->iscsi_name, devid->ident, ident_len);
8237716c1805SNattuvetty Bhavyan 		break;
8238716c1805SNattuvetty Bhavyan 
8239716c1805SNattuvetty Bhavyan 	case PROTOCOL_SRP:
8240716c1805SNattuvetty Bhavyan 		sz = sizeof (scsi_srp_transport_id_t);
8241716c1805SNattuvetty Bhavyan 		rpt = stmf_remote_port_alloc(sz);
8242716c1805SNattuvetty Bhavyan 		rpt->rport_tptid->format_code = 0;
8243716c1805SNattuvetty Bhavyan 		rpt->rport_tptid->protocol_id = devid->protocol_id;
8244716c1805SNattuvetty Bhavyan 		srp_tpd = (scsi_srp_transport_id_t *)rpt->rport_tptid;
8245716c1805SNattuvetty Bhavyan 		/*
8246716c1805SNattuvetty Bhavyan 		 * convert from "eui.xxxxxxxxxxxxxxx" to 8-byte binary
8247716c1805SNattuvetty Bhavyan 		 * skip first 4 byte for "eui."
8248716c1805SNattuvetty Bhavyan 		 * Assume 8-byte initiator-extension part of srp_name is NOT
8249716c1805SNattuvetty Bhavyan 		 * stored in devid and hence will be set as zero
8250716c1805SNattuvetty Bhavyan 		 */
8251716c1805SNattuvetty Bhavyan 		ASSERT(strncmp("eui.", (char *)devid->ident, 4) == 0);
8252716c1805SNattuvetty Bhavyan 		if ((ident_len < (SCSI_TPTID_SRP_PORT_NAME_LEN - 8) * 2 + 4) ||
8253716c1805SNattuvetty Bhavyan 		    !stmf_base16_str_to_binary((char *)devid->ident+4,
8254716c1805SNattuvetty Bhavyan 		    SCSI_TPTID_SRP_PORT_NAME_LEN, srp_tpd->srp_name))
8255716c1805SNattuvetty Bhavyan 			goto devid_to_remote_port_fail;
8256716c1805SNattuvetty Bhavyan 		break;
8257716c1805SNattuvetty Bhavyan 
8258716c1805SNattuvetty Bhavyan 	case PROTOCOL_PARALLEL_SCSI:
8259716c1805SNattuvetty Bhavyan 	case PROTOCOL_SSA:
8260716c1805SNattuvetty Bhavyan 	case PROTOCOL_IEEE_1394:
8261716c1805SNattuvetty Bhavyan 	case PROTOCOL_SAS:
8262716c1805SNattuvetty Bhavyan 	case PROTOCOL_ADT:
8263716c1805SNattuvetty Bhavyan 	case PROTOCOL_ATAPI:
8264716c1805SNattuvetty Bhavyan 	default :
8265716c1805SNattuvetty Bhavyan 		ident_len = devid->ident_length;
8266716c1805SNattuvetty Bhavyan 		sz = ALIGNED_TO_8BYTE_BOUNDARY(sizeof (stmf_dflt_scsi_tptid_t) +
8267716c1805SNattuvetty Bhavyan 		    ident_len - 1);
8268716c1805SNattuvetty Bhavyan 		rpt = stmf_remote_port_alloc(sz);
8269716c1805SNattuvetty Bhavyan 		rpt->rport_tptid->format_code = 0;
8270716c1805SNattuvetty Bhavyan 		rpt->rport_tptid->protocol_id = devid->protocol_id;
8271716c1805SNattuvetty Bhavyan 		dflt_tpd = (stmf_dflt_scsi_tptid_t *)rpt->rport_tptid;
8272716c1805SNattuvetty Bhavyan 		SCSI_WRITE16(dflt_tpd->ident_len, ident_len);
8273716c1805SNattuvetty Bhavyan 		(void) memcpy(dflt_tpd->ident, devid->ident, ident_len);
8274716c1805SNattuvetty Bhavyan 		break;
8275716c1805SNattuvetty Bhavyan 	}
8276716c1805SNattuvetty Bhavyan 	return (rpt);
8277716c1805SNattuvetty Bhavyan 
8278716c1805SNattuvetty Bhavyan devid_to_remote_port_fail:
8279716c1805SNattuvetty Bhavyan 	stmf_remote_port_free(rpt);
8280716c1805SNattuvetty Bhavyan 	return (NULL);
8281716c1805SNattuvetty Bhavyan 
8282716c1805SNattuvetty Bhavyan }
8283716c1805SNattuvetty Bhavyan 
8284716c1805SNattuvetty Bhavyan stmf_remote_port_t *
stmf_remote_port_alloc(uint16_t tptid_sz)8285bad5e468SToomas Soome stmf_remote_port_alloc(uint16_t tptid_sz)
8286bad5e468SToomas Soome {
8287716c1805SNattuvetty Bhavyan 	stmf_remote_port_t *rpt;
8288716c1805SNattuvetty Bhavyan 	rpt = (stmf_remote_port_t *)kmem_zalloc(
8289716c1805SNattuvetty Bhavyan 	    sizeof (stmf_remote_port_t) + tptid_sz, KM_SLEEP);
8290716c1805SNattuvetty Bhavyan 	rpt->rport_tptid_sz = tptid_sz;
8291716c1805SNattuvetty Bhavyan 	rpt->rport_tptid = (scsi_transport_id_t *)(rpt + 1);
8292716c1805SNattuvetty Bhavyan 	return (rpt);
8293716c1805SNattuvetty Bhavyan }
8294716c1805SNattuvetty Bhavyan 
8295716c1805SNattuvetty Bhavyan void
stmf_remote_port_free(stmf_remote_port_t * rpt)8296716c1805SNattuvetty Bhavyan stmf_remote_port_free(stmf_remote_port_t *rpt)
8297716c1805SNattuvetty Bhavyan {
8298716c1805SNattuvetty Bhavyan 	/*
8299716c1805SNattuvetty Bhavyan 	 * Note: stmf_scsilib_devid_to_remote_port() function allocates
8300716c1805SNattuvetty Bhavyan 	 *	remote port structures for all transports in the same way, So
8301716c1805SNattuvetty Bhavyan 	 *	it is safe to deallocate it in a protocol independent manner.
8302716c1805SNattuvetty Bhavyan 	 *	If any of the allocation method changes, corresponding changes
8303716c1805SNattuvetty Bhavyan 	 *	need to be made here too.
8304716c1805SNattuvetty Bhavyan 	 */
8305716c1805SNattuvetty Bhavyan 	kmem_free(rpt, sizeof (stmf_remote_port_t) + rpt->rport_tptid_sz);
8306716c1805SNattuvetty Bhavyan }
830761dfa509SRick McNeal 
830861dfa509SRick McNeal stmf_lu_t *
stmf_check_and_hold_lu(scsi_task_t * task,uint8_t * guid)830961dfa509SRick McNeal stmf_check_and_hold_lu(scsi_task_t *task, uint8_t *guid)
831061dfa509SRick McNeal {
831161dfa509SRick McNeal 	stmf_i_scsi_session_t *iss;
831261dfa509SRick McNeal 	stmf_lu_t *lu;
831361dfa509SRick McNeal 	stmf_i_lu_t *ilu = NULL;
831461dfa509SRick McNeal 	stmf_lun_map_t *sm;
831561dfa509SRick McNeal 	stmf_lun_map_ent_t *lme;
831661dfa509SRick McNeal 	int i;
831761dfa509SRick McNeal 
831861dfa509SRick McNeal 	iss = (stmf_i_scsi_session_t *)task->task_session->ss_stmf_private;
831961dfa509SRick McNeal 	rw_enter(iss->iss_lockp, RW_READER);
832061dfa509SRick McNeal 	sm = iss->iss_sm;
832161dfa509SRick McNeal 
832261dfa509SRick McNeal 	for (i = 0; i < sm->lm_nentries; i++) {
832361dfa509SRick McNeal 		if (sm->lm_plus[i] == NULL)
832461dfa509SRick McNeal 			continue;
832561dfa509SRick McNeal 		lme = (stmf_lun_map_ent_t *)sm->lm_plus[i];
832661dfa509SRick McNeal 		lu = lme->ent_lu;
832761dfa509SRick McNeal 		if (bcmp(lu->lu_id->ident, guid, 16) == 0) {
832861dfa509SRick McNeal 			break;
832961dfa509SRick McNeal 		}
833061dfa509SRick McNeal 		lu = NULL;
833161dfa509SRick McNeal 	}
833261dfa509SRick McNeal 
833361dfa509SRick McNeal 	if (!lu) {
833461dfa509SRick McNeal 		goto hold_lu_done;
833561dfa509SRick McNeal 	}
833661dfa509SRick McNeal 
833761dfa509SRick McNeal 	ilu = lu->lu_stmf_private;
833861dfa509SRick McNeal 	mutex_enter(&ilu->ilu_task_lock);
833961dfa509SRick McNeal 	ilu->ilu_additional_ref++;
834061dfa509SRick McNeal 	mutex_exit(&ilu->ilu_task_lock);
834161dfa509SRick McNeal 
834261dfa509SRick McNeal hold_lu_done:
834361dfa509SRick McNeal 	rw_exit(iss->iss_lockp);
834461dfa509SRick McNeal 	return (lu);
834561dfa509SRick McNeal }
834661dfa509SRick McNeal 
834761dfa509SRick McNeal void
stmf_release_lu(stmf_lu_t * lu)834861dfa509SRick McNeal stmf_release_lu(stmf_lu_t *lu)
834961dfa509SRick McNeal {
835061dfa509SRick McNeal 	stmf_i_lu_t *ilu;
835161dfa509SRick McNeal 
835261dfa509SRick McNeal 	ilu = lu->lu_stmf_private;
835361dfa509SRick McNeal 	ASSERT(ilu->ilu_additional_ref != 0);
835461dfa509SRick McNeal 	mutex_enter(&ilu->ilu_task_lock);
835561dfa509SRick McNeal 	ilu->ilu_additional_ref--;
835661dfa509SRick McNeal 	mutex_exit(&ilu->ilu_task_lock);
835761dfa509SRick McNeal }
835861dfa509SRick McNeal 
835961dfa509SRick McNeal int
stmf_is_task_being_aborted(scsi_task_t * task)836061dfa509SRick McNeal stmf_is_task_being_aborted(scsi_task_t *task)
836161dfa509SRick McNeal {
836261dfa509SRick McNeal 	stmf_i_scsi_task_t *itask;
836361dfa509SRick McNeal 
836461dfa509SRick McNeal 	itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
836561dfa509SRick McNeal 	if (itask->itask_flags & ITASK_BEING_ABORTED)
836661dfa509SRick McNeal 		return (1);
836761dfa509SRick McNeal 
836861dfa509SRick McNeal 	return (0);
836961dfa509SRick McNeal }
837061dfa509SRick McNeal 
837161dfa509SRick McNeal volatile boolean_t stmf_pgr_aptpl_always = B_FALSE;
837261dfa509SRick McNeal 
837361dfa509SRick McNeal boolean_t
stmf_is_pgr_aptpl_always()837461dfa509SRick McNeal stmf_is_pgr_aptpl_always()
837561dfa509SRick McNeal {
837661dfa509SRick McNeal 	return (stmf_pgr_aptpl_always);
837761dfa509SRick McNeal }
8378