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 */
21fcf3ce44SJohn Forte /*
223fb517f7SJames Moore * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23fcf3ce44SJohn Forte */
246ac72a9cSAlexander Stetsenko /*
25042f029eSAlexander Stetsenko * Copyright 2012, Nexenta Systems, Inc. All rights reserved.
26a49dc893SSaso Kiselkov * Copyright (c) 2013 by Delphix. All rights reserved.
27a49dc893SSaso Kiselkov * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
286ac72a9cSAlexander Stetsenko */
29fcf3ce44SJohn Forte
30fcf3ce44SJohn Forte #include <sys/conf.h>
31fcf3ce44SJohn Forte #include <sys/file.h>
32fcf3ce44SJohn Forte #include <sys/ddi.h>
33fcf3ce44SJohn Forte #include <sys/sunddi.h>
34fcf3ce44SJohn Forte #include <sys/modctl.h>
35fcf3ce44SJohn Forte #include <sys/scsi/scsi.h>
36716c1805SNattuvetty Bhavyan #include <sys/scsi/generic/persist.h>
37fcf3ce44SJohn Forte #include <sys/scsi/impl/scsi_reset_notify.h>
38fcf3ce44SJohn Forte #include <sys/disp.h>
39fcf3ce44SJohn Forte #include <sys/byteorder.h>
40fcf3ce44SJohn Forte #include <sys/atomic.h>
41fcf3ce44SJohn Forte #include <sys/ethernet.h>
42fcf3ce44SJohn Forte #include <sys/sdt.h>
43fcf3ce44SJohn Forte #include <sys/nvpair.h>
445679c89fSjv227347 #include <sys/zone.h>
45427fcaf8Stim szeto #include <sys/id_space.h>
46fcf3ce44SJohn Forte
474558d122SViswanathan Kannappan #include <sys/stmf.h>
484558d122SViswanathan Kannappan #include <sys/lpif.h>
494558d122SViswanathan Kannappan #include <sys/portif.h>
504558d122SViswanathan Kannappan #include <sys/stmf_ioctl.h>
514558d122SViswanathan Kannappan #include <sys/pppt_ic_if.h>
524558d122SViswanathan Kannappan
534558d122SViswanathan Kannappan #include "stmf_impl.h"
544558d122SViswanathan Kannappan #include "lun_map.h"
554558d122SViswanathan Kannappan #include "stmf_state.h"
564558d122SViswanathan Kannappan #include "stmf_stats.h"
57fcf3ce44SJohn Forte
58780c822cStim szeto /*
59780c822cStim szeto * Lock order:
60780c822cStim szeto * stmf_state_lock --> ilport_lock/iss_lockp --> ilu_task_lock
61780c822cStim szeto */
62780c822cStim szeto
63fcf3ce44SJohn Forte static uint64_t stmf_session_counter = 0;
64fcf3ce44SJohn Forte static uint16_t stmf_rtpid_counter = 0;
6545039663SJohn Forte /* start messages at 1 */
6645039663SJohn Forte static uint64_t stmf_proxy_msg_id = 1;
67cbdc6dc7SJohn Forte #define MSG_ID_TM_BIT 0x8000000000000000
68716c1805SNattuvetty Bhavyan #define ALIGNED_TO_8BYTE_BOUNDARY(i) (((i) + 7) & ~7)
69fcf3ce44SJohn Forte
70a49dc893SSaso Kiselkov /*
71a49dc893SSaso Kiselkov * When stmf_io_deadman_enabled is set to B_TRUE, we check that finishing up
72a49dc893SSaso Kiselkov * I/O operations on an offlining LU doesn't take longer than stmf_io_deadman
73a49dc893SSaso Kiselkov * seconds. If it does, we trigger a panic to inform the user of hung I/O
74a49dc893SSaso Kiselkov * blocking us for too long.
75a49dc893SSaso Kiselkov */
76a49dc893SSaso Kiselkov boolean_t stmf_io_deadman_enabled = B_TRUE;
77a49dc893SSaso Kiselkov int stmf_io_deadman = 1000; /* seconds */
78a49dc893SSaso Kiselkov
79042f029eSAlexander Stetsenko struct stmf_svc_clocks;
80042f029eSAlexander Stetsenko
81fcf3ce44SJohn Forte static int stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
82fcf3ce44SJohn Forte static int stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
83fcf3ce44SJohn Forte static int stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
84fcf3ce44SJohn Forte void **result);
85fcf3ce44SJohn Forte static int stmf_open(dev_t *devp, int flag, int otype, cred_t *credp);
86fcf3ce44SJohn Forte static int stmf_close(dev_t dev, int flag, int otype, cred_t *credp);
87fcf3ce44SJohn Forte static int stmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
88fcf3ce44SJohn Forte cred_t *credp, int *rval);
89fcf3ce44SJohn Forte static int stmf_get_stmf_state(stmf_state_desc_t *std);
90fcf3ce44SJohn Forte static int stmf_set_stmf_state(stmf_state_desc_t *std);
91fcf3ce44SJohn Forte static void stmf_abort_task_offline(scsi_task_t *task, int offline_lu,
92fcf3ce44SJohn Forte char *info);
9345039663SJohn Forte static int stmf_set_alua_state(stmf_alua_state_desc_t *alua_state);
9445039663SJohn Forte static void stmf_get_alua_state(stmf_alua_state_desc_t *alua_state);
9540c3e8ffSJohn Forte
9640c3e8ffSJohn Forte static void stmf_task_audit(stmf_i_scsi_task_t *itask,
9740c3e8ffSJohn Forte task_audit_event_t te, uint32_t cmd_or_iof, stmf_data_buf_t *dbuf);
9840c3e8ffSJohn Forte
99716c1805SNattuvetty Bhavyan static boolean_t stmf_base16_str_to_binary(char *c, int dplen, uint8_t *dp);
100716c1805SNattuvetty Bhavyan static char stmf_ctoi(char c);
10145039663SJohn Forte stmf_xfer_data_t *stmf_prepare_tpgs_data(uint8_t ilu_alua);
102fcf3ce44SJohn Forte void stmf_svc_init();
103fcf3ce44SJohn Forte stmf_status_t stmf_svc_fini();
104fcf3ce44SJohn Forte void stmf_svc(void *arg);
105a49dc893SSaso Kiselkov static void stmf_wait_ilu_tasks_finish(stmf_i_lu_t *ilu);
106fcf3ce44SJohn Forte void stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info);
1076ac72a9cSAlexander Stetsenko static void stmf_svc_kill_obj_requests(void *obj);
108042f029eSAlexander Stetsenko static void stmf_svc_timeout(struct stmf_svc_clocks *);
109fcf3ce44SJohn Forte void stmf_check_freetask();
110fcf3ce44SJohn Forte void stmf_abort_target_reset(scsi_task_t *task);
111fcf3ce44SJohn Forte stmf_status_t stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task,
112fcf3ce44SJohn Forte int target_reset);
113fcf3ce44SJohn Forte void stmf_target_reset_poll(struct scsi_task *task);
114fcf3ce44SJohn Forte void stmf_handle_lun_reset(scsi_task_t *task);
115fcf3ce44SJohn Forte void stmf_handle_target_reset(scsi_task_t *task);
11691159e90SJohn Forte void stmf_xd_to_dbuf(stmf_data_buf_t *dbuf, int set_rel_off);
1178fe96085Stim szeto int stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
1188fe96085Stim szeto uint32_t *err_ret);
119fcf3ce44SJohn Forte int stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi);
1208fe96085Stim szeto int stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
1218fe96085Stim szeto uint32_t *err_ret);
122fcf3ce44SJohn Forte void stmf_delete_ppd(stmf_pp_data_t *ppd);
123fcf3ce44SJohn Forte void stmf_delete_all_ppds();
124fcf3ce44SJohn Forte void stmf_trace_clear();
125fcf3ce44SJohn Forte void stmf_worker_init();
126fcf3ce44SJohn Forte stmf_status_t stmf_worker_fini();
127fcf3ce44SJohn Forte void stmf_worker_mgmt();
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 *);
167034d83c4Stim szeto
168427fcaf8Stim szeto static int stmf_irport_compare(const void *void_irport1,
169427fcaf8Stim szeto const void *void_irport2);
170427fcaf8Stim szeto static stmf_i_remote_port_t *stmf_irport_create(scsi_devid_desc_t *rport_devid);
171427fcaf8Stim szeto static void stmf_irport_destroy(stmf_i_remote_port_t *irport);
172427fcaf8Stim szeto static stmf_i_remote_port_t *stmf_irport_register(
173427fcaf8Stim szeto scsi_devid_desc_t *rport_devid);
174427fcaf8Stim szeto static stmf_i_remote_port_t *stmf_irport_lookup_locked(
175427fcaf8Stim szeto scsi_devid_desc_t *rport_devid);
176427fcaf8Stim szeto static void stmf_irport_deregister(stmf_i_remote_port_t *irport);
177427fcaf8Stim szeto
178fcf3ce44SJohn Forte extern struct mod_ops mod_driverops;
179fcf3ce44SJohn Forte
180fcf3ce44SJohn Forte /* =====[ Tunables ]===== */
181fcf3ce44SJohn Forte /* Internal tracing */
182fcf3ce44SJohn Forte volatile int stmf_trace_on = 1;
183fcf3ce44SJohn Forte volatile int stmf_trace_buf_size = (1 * 1024 * 1024);
184fcf3ce44SJohn Forte /*
185fcf3ce44SJohn Forte * The reason default task timeout is 75 is because we want the
186fcf3ce44SJohn Forte * host to timeout 1st and mostly host timeout is 60 seconds.
187fcf3ce44SJohn Forte */
188fcf3ce44SJohn Forte volatile int stmf_default_task_timeout = 75;
189fcf3ce44SJohn Forte /*
190fcf3ce44SJohn Forte * Setting this to one means, you are responsible for config load and keeping
191fcf3ce44SJohn Forte * things in sync with persistent database.
192fcf3ce44SJohn Forte */
193fcf3ce44SJohn Forte volatile int stmf_allow_modunload = 0;
194fcf3ce44SJohn Forte
195fcf3ce44SJohn Forte volatile int stmf_max_nworkers = 256;
196fcf3ce44SJohn Forte volatile int stmf_min_nworkers = 4;
197fcf3ce44SJohn Forte volatile int stmf_worker_scale_down_delay = 20;
198fcf3ce44SJohn Forte
199fcf3ce44SJohn Forte /* === [ Debugging and fault injection ] === */
200fcf3ce44SJohn Forte #ifdef DEBUG
201*9c68c052SJosef 'Jeff' Sipek volatile uint32_t stmf_drop_task_counter = 0;
202*9c68c052SJosef 'Jeff' Sipek volatile uint32_t stmf_drop_buf_counter = 0;
203fcf3ce44SJohn Forte
204fcf3ce44SJohn Forte #endif
205fcf3ce44SJohn Forte
206fcf3ce44SJohn Forte stmf_state_t stmf_state;
207fcf3ce44SJohn Forte static stmf_lu_t *dlun0;
208fcf3ce44SJohn Forte
209fcf3ce44SJohn Forte static uint8_t stmf_first_zero[] =
210fcf3ce44SJohn Forte { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0xff };
211fcf3ce44SJohn Forte static uint8_t stmf_first_one[] =
212fcf3ce44SJohn Forte { 0xff, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
213fcf3ce44SJohn Forte
214fcf3ce44SJohn Forte static kmutex_t trace_buf_lock;
215fcf3ce44SJohn Forte static int trace_buf_size;
216fcf3ce44SJohn Forte static int trace_buf_curndx;
217fcf3ce44SJohn Forte caddr_t stmf_trace_buf;
218fcf3ce44SJohn Forte
219fcf3ce44SJohn Forte static enum {
220fcf3ce44SJohn Forte STMF_WORKERS_DISABLED = 0,
221fcf3ce44SJohn Forte STMF_WORKERS_ENABLING,
222fcf3ce44SJohn Forte STMF_WORKERS_ENABLED
223fcf3ce44SJohn Forte } stmf_workers_state = STMF_WORKERS_DISABLED;
224fcf3ce44SJohn Forte static int stmf_i_max_nworkers;
225fcf3ce44SJohn Forte static int stmf_i_min_nworkers;
226fcf3ce44SJohn Forte static int stmf_nworkers_cur; /* # of workers currently running */
227fcf3ce44SJohn Forte static int stmf_nworkers_needed; /* # of workers need to be running */
228fcf3ce44SJohn Forte static int stmf_worker_sel_counter = 0;
229fcf3ce44SJohn Forte static uint32_t stmf_cur_ntasks = 0;
230fcf3ce44SJohn Forte static clock_t stmf_wm_last = 0;
231fcf3ce44SJohn Forte /*
232fcf3ce44SJohn Forte * This is equal to stmf_nworkers_cur while we are increasing # workers and
233fcf3ce44SJohn Forte * stmf_nworkers_needed while we are decreasing the worker count.
234fcf3ce44SJohn Forte */
235fcf3ce44SJohn Forte static int stmf_nworkers_accepting_cmds;
236fcf3ce44SJohn Forte static stmf_worker_t *stmf_workers = NULL;
237fcf3ce44SJohn Forte static clock_t stmf_worker_mgmt_delay = 2;
238fcf3ce44SJohn Forte static clock_t stmf_worker_scale_down_timer = 0;
239fcf3ce44SJohn Forte static int stmf_worker_scale_down_qd = 0;
240fcf3ce44SJohn Forte
241fcf3ce44SJohn Forte static struct cb_ops stmf_cb_ops = {
242fcf3ce44SJohn Forte stmf_open, /* open */
243fcf3ce44SJohn Forte stmf_close, /* close */
244fcf3ce44SJohn Forte nodev, /* strategy */
245fcf3ce44SJohn Forte nodev, /* print */
246fcf3ce44SJohn Forte nodev, /* dump */
247fcf3ce44SJohn Forte nodev, /* read */
248fcf3ce44SJohn Forte nodev, /* write */
249fcf3ce44SJohn Forte stmf_ioctl, /* ioctl */
250fcf3ce44SJohn Forte nodev, /* devmap */
251fcf3ce44SJohn Forte nodev, /* mmap */
252fcf3ce44SJohn Forte nodev, /* segmap */
253fcf3ce44SJohn Forte nochpoll, /* chpoll */
254fcf3ce44SJohn Forte ddi_prop_op, /* cb_prop_op */
255fcf3ce44SJohn Forte 0, /* streamtab */
256fcf3ce44SJohn Forte D_NEW | D_MP, /* cb_flag */
257fcf3ce44SJohn Forte CB_REV, /* rev */
258fcf3ce44SJohn Forte nodev, /* aread */
259fcf3ce44SJohn Forte nodev /* awrite */
260fcf3ce44SJohn Forte };
261fcf3ce44SJohn Forte
262fcf3ce44SJohn Forte static struct dev_ops stmf_ops = {
263fcf3ce44SJohn Forte DEVO_REV,
264fcf3ce44SJohn Forte 0,
265fcf3ce44SJohn Forte stmf_getinfo,
266fcf3ce44SJohn Forte nulldev, /* identify */
267fcf3ce44SJohn Forte nulldev, /* probe */
268fcf3ce44SJohn Forte stmf_attach,
269fcf3ce44SJohn Forte stmf_detach,
270fcf3ce44SJohn Forte nodev, /* reset */
271fcf3ce44SJohn Forte &stmf_cb_ops,
272fcf3ce44SJohn Forte NULL, /* bus_ops */
273fcf3ce44SJohn Forte NULL /* power */
274fcf3ce44SJohn Forte };
275fcf3ce44SJohn Forte
276fcf3ce44SJohn Forte #define STMF_NAME "COMSTAR STMF"
277034d83c4Stim szeto #define STMF_MODULE_NAME "stmf"
278fcf3ce44SJohn Forte
279fcf3ce44SJohn Forte static struct modldrv modldrv = {
280fcf3ce44SJohn Forte &mod_driverops,
281fcf3ce44SJohn Forte STMF_NAME,
282fcf3ce44SJohn Forte &stmf_ops
283fcf3ce44SJohn Forte };
284fcf3ce44SJohn Forte
285fcf3ce44SJohn Forte static struct modlinkage modlinkage = {
286fcf3ce44SJohn Forte MODREV_1,
287fcf3ce44SJohn Forte &modldrv,
288fcf3ce44SJohn Forte NULL
289fcf3ce44SJohn Forte };
290fcf3ce44SJohn Forte
291fcf3ce44SJohn Forte int
_init(void)292fcf3ce44SJohn Forte _init(void)
293fcf3ce44SJohn Forte {
294fcf3ce44SJohn Forte int ret;
295fcf3ce44SJohn Forte
296fcf3ce44SJohn Forte ret = mod_install(&modlinkage);
297fcf3ce44SJohn Forte if (ret)
298fcf3ce44SJohn Forte return (ret);
299fcf3ce44SJohn Forte stmf_trace_buf = kmem_zalloc(stmf_trace_buf_size, KM_SLEEP);
300fcf3ce44SJohn Forte trace_buf_size = stmf_trace_buf_size;
301fcf3ce44SJohn Forte trace_buf_curndx = 0;
302fcf3ce44SJohn Forte mutex_init(&trace_buf_lock, NULL, MUTEX_DRIVER, 0);
303fcf3ce44SJohn Forte bzero(&stmf_state, sizeof (stmf_state_t));
304fcf3ce44SJohn Forte /* STMF service is off by default */
305fcf3ce44SJohn Forte stmf_state.stmf_service_running = 0;
3064b31676fSsrivijitha dugganapalli /* default lu/lport states are online */
3074b31676fSsrivijitha dugganapalli stmf_state.stmf_default_lu_state = STMF_STATE_ONLINE;
3084b31676fSsrivijitha dugganapalli stmf_state.stmf_default_lport_state = STMF_STATE_ONLINE;
309fcf3ce44SJohn Forte mutex_init(&stmf_state.stmf_lock, NULL, MUTEX_DRIVER, NULL);
310fcf3ce44SJohn Forte cv_init(&stmf_state.stmf_cv, NULL, CV_DRIVER, NULL);
311fcf3ce44SJohn Forte stmf_session_counter = (uint64_t)ddi_get_lbolt();
312427fcaf8Stim szeto avl_create(&stmf_state.stmf_irportlist,
313427fcaf8Stim szeto stmf_irport_compare, sizeof (stmf_i_remote_port_t),
314427fcaf8Stim szeto offsetof(stmf_i_remote_port_t, irport_ln));
315427fcaf8Stim szeto stmf_state.stmf_ilport_inst_space =
316427fcaf8Stim szeto id_space_create("lport-instances", 0, MAX_ILPORT);
317427fcaf8Stim szeto stmf_state.stmf_irport_inst_space =
318427fcaf8Stim szeto id_space_create("rport-instances", 0, MAX_IRPORT);
319fcf3ce44SJohn Forte stmf_view_init();
320fcf3ce44SJohn Forte stmf_svc_init();
321fcf3ce44SJohn Forte stmf_dlun_init();
322fcf3ce44SJohn Forte return (ret);
323fcf3ce44SJohn Forte }
324fcf3ce44SJohn Forte
325fcf3ce44SJohn Forte int
_fini(void)326fcf3ce44SJohn Forte _fini(void)
327fcf3ce44SJohn Forte {
328fcf3ce44SJohn Forte int ret;
329427fcaf8Stim szeto stmf_i_remote_port_t *irport;
330427fcaf8Stim szeto void *avl_dest_cookie = NULL;
331fcf3ce44SJohn Forte
332fcf3ce44SJohn Forte if (stmf_state.stmf_service_running)
333fcf3ce44SJohn Forte return (EBUSY);
334fcf3ce44SJohn Forte if ((!stmf_allow_modunload) &&
335fcf3ce44SJohn Forte (stmf_state.stmf_config_state != STMF_CONFIG_NONE)) {
336fcf3ce44SJohn Forte return (EBUSY);
337fcf3ce44SJohn Forte }
338fcf3ce44SJohn Forte if (stmf_state.stmf_nlps || stmf_state.stmf_npps) {
339fcf3ce44SJohn Forte return (EBUSY);
340fcf3ce44SJohn Forte }
341fcf3ce44SJohn Forte if (stmf_dlun_fini() != STMF_SUCCESS)
342fcf3ce44SJohn Forte return (EBUSY);
343fcf3ce44SJohn Forte if (stmf_worker_fini() != STMF_SUCCESS) {
344fcf3ce44SJohn Forte stmf_dlun_init();
345fcf3ce44SJohn Forte return (EBUSY);
346fcf3ce44SJohn Forte }
347fcf3ce44SJohn Forte if (stmf_svc_fini() != STMF_SUCCESS) {
348fcf3ce44SJohn Forte stmf_dlun_init();
349fcf3ce44SJohn Forte stmf_worker_init();
350fcf3ce44SJohn Forte return (EBUSY);
351fcf3ce44SJohn Forte }
352fcf3ce44SJohn Forte
353fcf3ce44SJohn Forte ret = mod_remove(&modlinkage);
354fcf3ce44SJohn Forte if (ret) {
355fcf3ce44SJohn Forte stmf_svc_init();
356fcf3ce44SJohn Forte stmf_dlun_init();
357fcf3ce44SJohn Forte stmf_worker_init();
358fcf3ce44SJohn Forte return (ret);
359fcf3ce44SJohn Forte }
360fcf3ce44SJohn Forte
361fcf3ce44SJohn Forte stmf_view_clear_config();
362427fcaf8Stim szeto
363427fcaf8Stim szeto while ((irport = avl_destroy_nodes(&stmf_state.stmf_irportlist,
364427fcaf8Stim szeto &avl_dest_cookie)) != NULL)
365427fcaf8Stim szeto stmf_irport_destroy(irport);
366427fcaf8Stim szeto avl_destroy(&stmf_state.stmf_irportlist);
367427fcaf8Stim szeto id_space_destroy(stmf_state.stmf_ilport_inst_space);
368427fcaf8Stim szeto id_space_destroy(stmf_state.stmf_irport_inst_space);
369427fcaf8Stim szeto
370fcf3ce44SJohn Forte kmem_free(stmf_trace_buf, stmf_trace_buf_size);
371fcf3ce44SJohn Forte mutex_destroy(&trace_buf_lock);
372fcf3ce44SJohn Forte mutex_destroy(&stmf_state.stmf_lock);
373fcf3ce44SJohn Forte cv_destroy(&stmf_state.stmf_cv);
374fcf3ce44SJohn Forte return (ret);
375fcf3ce44SJohn Forte }
376fcf3ce44SJohn Forte
377fcf3ce44SJohn Forte int
_info(struct modinfo * modinfop)378fcf3ce44SJohn Forte _info(struct modinfo *modinfop)
379fcf3ce44SJohn Forte {
380fcf3ce44SJohn Forte return (mod_info(&modlinkage, modinfop));
381fcf3ce44SJohn Forte }
382fcf3ce44SJohn Forte
383fcf3ce44SJohn Forte /* ARGSUSED */
384fcf3ce44SJohn Forte static int
stmf_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)385fcf3ce44SJohn Forte stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
386fcf3ce44SJohn Forte {
387fcf3ce44SJohn Forte switch (cmd) {
388fcf3ce44SJohn Forte case DDI_INFO_DEVT2DEVINFO:
389fcf3ce44SJohn Forte *result = stmf_state.stmf_dip;
390fcf3ce44SJohn Forte break;
391fcf3ce44SJohn Forte case DDI_INFO_DEVT2INSTANCE:
3928fe96085Stim szeto *result =
3938fe96085Stim szeto (void *)(uintptr_t)ddi_get_instance(stmf_state.stmf_dip);
394fcf3ce44SJohn Forte break;
395fcf3ce44SJohn Forte default:
396fcf3ce44SJohn Forte return (DDI_FAILURE);
397fcf3ce44SJohn Forte }
398fcf3ce44SJohn Forte
399fcf3ce44SJohn Forte return (DDI_SUCCESS);
400fcf3ce44SJohn Forte }
401fcf3ce44SJohn Forte
402fcf3ce44SJohn Forte static int
stmf_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)403fcf3ce44SJohn Forte stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
404fcf3ce44SJohn Forte {
405fcf3ce44SJohn Forte switch (cmd) {
406fcf3ce44SJohn Forte case DDI_ATTACH:
407fcf3ce44SJohn Forte stmf_state.stmf_dip = dip;
408fcf3ce44SJohn Forte
409fcf3ce44SJohn Forte if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
410fcf3ce44SJohn Forte DDI_NT_STMF, 0) != DDI_SUCCESS) {
411fcf3ce44SJohn Forte break;
412fcf3ce44SJohn Forte }
413fcf3ce44SJohn Forte ddi_report_dev(dip);
414fcf3ce44SJohn Forte return (DDI_SUCCESS);
415fcf3ce44SJohn Forte }
416fcf3ce44SJohn Forte
417fcf3ce44SJohn Forte return (DDI_FAILURE);
418fcf3ce44SJohn Forte }
419fcf3ce44SJohn Forte
420fcf3ce44SJohn Forte static int
stmf_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)421fcf3ce44SJohn Forte stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
422fcf3ce44SJohn Forte {
423fcf3ce44SJohn Forte switch (cmd) {
424fcf3ce44SJohn Forte case DDI_DETACH:
425fcf3ce44SJohn Forte ddi_remove_minor_node(dip, 0);
426fcf3ce44SJohn Forte return (DDI_SUCCESS);
427fcf3ce44SJohn Forte }
428fcf3ce44SJohn Forte
429fcf3ce44SJohn Forte return (DDI_FAILURE);
430fcf3ce44SJohn Forte }
431fcf3ce44SJohn Forte
432fcf3ce44SJohn Forte /* ARGSUSED */
433fcf3ce44SJohn Forte static int
stmf_open(dev_t * devp,int flag,int otype,cred_t * credp)434fcf3ce44SJohn Forte stmf_open(dev_t *devp, int flag, int otype, cred_t *credp)
435fcf3ce44SJohn Forte {
436fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
437fcf3ce44SJohn Forte if (stmf_state.stmf_exclusive_open) {
438fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
439fcf3ce44SJohn Forte return (EBUSY);
440fcf3ce44SJohn Forte }
441fcf3ce44SJohn Forte if (flag & FEXCL) {
442fcf3ce44SJohn Forte if (stmf_state.stmf_opened) {
443fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
444fcf3ce44SJohn Forte return (EBUSY);
445fcf3ce44SJohn Forte }
446fcf3ce44SJohn Forte stmf_state.stmf_exclusive_open = 1;
447fcf3ce44SJohn Forte }
448fcf3ce44SJohn Forte stmf_state.stmf_opened = 1;
449fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
450fcf3ce44SJohn Forte return (0);
451fcf3ce44SJohn Forte }
452fcf3ce44SJohn Forte
453fcf3ce44SJohn Forte /* ARGSUSED */
454fcf3ce44SJohn Forte static int
stmf_close(dev_t dev,int flag,int otype,cred_t * credp)455fcf3ce44SJohn Forte stmf_close(dev_t dev, int flag, int otype, cred_t *credp)
456fcf3ce44SJohn Forte {
457fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
458fcf3ce44SJohn Forte stmf_state.stmf_opened = 0;
459fcf3ce44SJohn Forte if (stmf_state.stmf_exclusive_open &&
460fcf3ce44SJohn Forte (stmf_state.stmf_config_state != STMF_CONFIG_INIT_DONE)) {
461fcf3ce44SJohn Forte stmf_state.stmf_config_state = STMF_CONFIG_NONE;
462fcf3ce44SJohn Forte stmf_delete_all_ppds();
463fcf3ce44SJohn Forte stmf_view_clear_config();
464fcf3ce44SJohn Forte stmf_view_init();
465fcf3ce44SJohn Forte }
466fcf3ce44SJohn Forte stmf_state.stmf_exclusive_open = 0;
467fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
468fcf3ce44SJohn Forte return (0);
469fcf3ce44SJohn Forte }
470fcf3ce44SJohn Forte
471fcf3ce44SJohn Forte int
stmf_copyin_iocdata(intptr_t data,int mode,stmf_iocdata_t ** iocd,void ** ibuf,void ** obuf)472fcf3ce44SJohn Forte stmf_copyin_iocdata(intptr_t data, int mode, stmf_iocdata_t **iocd,
473fcf3ce44SJohn Forte void **ibuf, void **obuf)
474fcf3ce44SJohn Forte {
475fcf3ce44SJohn Forte int ret;
476fcf3ce44SJohn Forte
477fcf3ce44SJohn Forte *ibuf = NULL;
478fcf3ce44SJohn Forte *obuf = NULL;
479fcf3ce44SJohn Forte *iocd = kmem_zalloc(sizeof (stmf_iocdata_t), KM_SLEEP);
480fcf3ce44SJohn Forte
481fcf3ce44SJohn Forte ret = ddi_copyin((void *)data, *iocd, sizeof (stmf_iocdata_t), mode);
482fcf3ce44SJohn Forte if (ret)
483fcf3ce44SJohn Forte return (EFAULT);
484fcf3ce44SJohn Forte if ((*iocd)->stmf_version != STMF_VERSION_1) {
485fcf3ce44SJohn Forte ret = EINVAL;
486fcf3ce44SJohn Forte goto copyin_iocdata_done;
487fcf3ce44SJohn Forte }
488fcf3ce44SJohn Forte if ((*iocd)->stmf_ibuf_size) {
489fcf3ce44SJohn Forte *ibuf = kmem_zalloc((*iocd)->stmf_ibuf_size, KM_SLEEP);
490fcf3ce44SJohn Forte ret = ddi_copyin((void *)((unsigned long)(*iocd)->stmf_ibuf),
491fcf3ce44SJohn Forte *ibuf, (*iocd)->stmf_ibuf_size, mode);
492fcf3ce44SJohn Forte }
493fcf3ce44SJohn Forte if ((*iocd)->stmf_obuf_size)
494fcf3ce44SJohn Forte *obuf = kmem_zalloc((*iocd)->stmf_obuf_size, KM_SLEEP);
495fcf3ce44SJohn Forte
496fcf3ce44SJohn Forte if (ret == 0)
497fcf3ce44SJohn Forte return (0);
498fcf3ce44SJohn Forte ret = EFAULT;
499fcf3ce44SJohn Forte copyin_iocdata_done:;
500fcf3ce44SJohn Forte if (*obuf) {
501fcf3ce44SJohn Forte kmem_free(*obuf, (*iocd)->stmf_obuf_size);
502fcf3ce44SJohn Forte *obuf = NULL;
503fcf3ce44SJohn Forte }
504fcf3ce44SJohn Forte if (*ibuf) {
505fcf3ce44SJohn Forte kmem_free(*ibuf, (*iocd)->stmf_ibuf_size);
506fcf3ce44SJohn Forte *ibuf = NULL;
507fcf3ce44SJohn Forte }
508fcf3ce44SJohn Forte kmem_free(*iocd, sizeof (stmf_iocdata_t));
509fcf3ce44SJohn Forte return (ret);
510fcf3ce44SJohn Forte }
511fcf3ce44SJohn Forte
512fcf3ce44SJohn Forte int
stmf_copyout_iocdata(intptr_t data,int mode,stmf_iocdata_t * iocd,void * obuf)513fcf3ce44SJohn Forte stmf_copyout_iocdata(intptr_t data, int mode, stmf_iocdata_t *iocd, void *obuf)
514fcf3ce44SJohn Forte {
515fcf3ce44SJohn Forte int ret;
516fcf3ce44SJohn Forte
517fcf3ce44SJohn Forte if (iocd->stmf_obuf_size) {
518fcf3ce44SJohn Forte ret = ddi_copyout(obuf, (void *)(unsigned long)iocd->stmf_obuf,
519fcf3ce44SJohn Forte iocd->stmf_obuf_size, mode);
520fcf3ce44SJohn Forte if (ret)
521fcf3ce44SJohn Forte return (EFAULT);
522fcf3ce44SJohn Forte }
523fcf3ce44SJohn Forte ret = ddi_copyout(iocd, (void *)data, sizeof (stmf_iocdata_t), mode);
524fcf3ce44SJohn Forte if (ret)
525fcf3ce44SJohn Forte return (EFAULT);
526fcf3ce44SJohn Forte return (0);
527fcf3ce44SJohn Forte }
528fcf3ce44SJohn Forte
529fcf3ce44SJohn Forte /* ARGSUSED */
530fcf3ce44SJohn Forte static int
stmf_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * credp,int * rval)531fcf3ce44SJohn Forte stmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
532fcf3ce44SJohn Forte cred_t *credp, int *rval)
533fcf3ce44SJohn Forte {
534fcf3ce44SJohn Forte stmf_iocdata_t *iocd;
535fcf3ce44SJohn Forte void *ibuf = NULL, *obuf = NULL;
536fcf3ce44SJohn Forte slist_lu_t *luid_list;
537fcf3ce44SJohn Forte slist_target_port_t *lportid_list;
538fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
539fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
540fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
541fcf3ce44SJohn Forte slist_scsi_session_t *iss_list;
542fcf3ce44SJohn Forte sioc_lu_props_t *lup;
543fcf3ce44SJohn Forte sioc_target_port_props_t *lportp;
5448fe96085Stim szeto stmf_ppioctl_data_t *ppi, *ppi_out = NULL;
5458fe96085Stim szeto uint64_t *ppi_token = NULL;
5468fe96085Stim szeto uint8_t *p_id, *id;
547fcf3ce44SJohn Forte stmf_state_desc_t *std;
548fcf3ce44SJohn Forte stmf_status_t ctl_ret;
549fcf3ce44SJohn Forte stmf_state_change_info_t ssi;
550fcf3ce44SJohn Forte int ret = 0;
551fcf3ce44SJohn Forte uint32_t n;
552fcf3ce44SJohn Forte int i;
553fcf3ce44SJohn Forte stmf_group_op_data_t *grp_entry;
554fcf3ce44SJohn Forte stmf_group_name_t *grpname;
555fcf3ce44SJohn Forte stmf_view_op_entry_t *ve;
556fcf3ce44SJohn Forte stmf_id_type_t idtype;
557fcf3ce44SJohn Forte stmf_id_data_t *id_entry;
558fcf3ce44SJohn Forte stmf_id_list_t *id_list;
559fcf3ce44SJohn Forte stmf_view_entry_t *view_entry;
5604b31676fSsrivijitha dugganapalli stmf_set_props_t *stmf_set_props;
561fcf3ce44SJohn Forte uint32_t veid;
562fcf3ce44SJohn Forte if ((cmd & 0xff000000) != STMF_IOCTL) {
563fcf3ce44SJohn Forte return (ENOTTY);
564fcf3ce44SJohn Forte }
565fcf3ce44SJohn Forte
566fcf3ce44SJohn Forte if (drv_priv(credp) != 0) {
567fcf3ce44SJohn Forte return (EPERM);
568fcf3ce44SJohn Forte }
569fcf3ce44SJohn Forte
570fcf3ce44SJohn Forte ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
571fcf3ce44SJohn Forte if (ret)
572fcf3ce44SJohn Forte return (ret);
573fcf3ce44SJohn Forte iocd->stmf_error = 0;
574fcf3ce44SJohn Forte
575fcf3ce44SJohn Forte switch (cmd) {
576fcf3ce44SJohn Forte case STMF_IOCTL_LU_LIST:
5778fe96085Stim szeto /* retrieves both registered/unregistered */
5788fe96085Stim szeto mutex_enter(&stmf_state.stmf_lock);
5798fe96085Stim szeto id_list = &stmf_state.stmf_luid_list;
5808fe96085Stim szeto n = min(id_list->id_count,
5818fe96085Stim szeto (iocd->stmf_obuf_size)/sizeof (slist_lu_t));
5828fe96085Stim szeto iocd->stmf_obuf_max_nentries = id_list->id_count;
5838fe96085Stim szeto luid_list = (slist_lu_t *)obuf;
5848fe96085Stim szeto id_entry = id_list->idl_head;
5858fe96085Stim szeto for (i = 0; i < n; i++) {
5868fe96085Stim szeto bcopy(id_entry->id_data, luid_list[i].lu_guid, 16);
5878fe96085Stim szeto id_entry = id_entry->id_next;
5888fe96085Stim szeto }
5898fe96085Stim szeto
5908fe96085Stim szeto n = iocd->stmf_obuf_size/sizeof (slist_lu_t);
5918fe96085Stim szeto for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
5928fe96085Stim szeto id = (uint8_t *)ilu->ilu_lu->lu_id;
5938fe96085Stim szeto if (stmf_lookup_id(id_list, 16, id + 4) == NULL) {
5948fe96085Stim szeto iocd->stmf_obuf_max_nentries++;
5958fe96085Stim szeto if (i < n) {
5968fe96085Stim szeto bcopy(id + 4, luid_list[i].lu_guid,
5978fe96085Stim szeto sizeof (slist_lu_t));
5988fe96085Stim szeto i++;
5998fe96085Stim szeto }
6008fe96085Stim szeto }
6018fe96085Stim szeto }
6028fe96085Stim szeto iocd->stmf_obuf_nentries = i;
6038fe96085Stim szeto mutex_exit(&stmf_state.stmf_lock);
6048fe96085Stim szeto break;
6058fe96085Stim szeto
6068fe96085Stim szeto case STMF_IOCTL_REG_LU_LIST:
607fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
608fcf3ce44SJohn Forte iocd->stmf_obuf_max_nentries = stmf_state.stmf_nlus;
609fcf3ce44SJohn Forte n = min(stmf_state.stmf_nlus,
610fcf3ce44SJohn Forte (iocd->stmf_obuf_size)/sizeof (slist_lu_t));
611fcf3ce44SJohn Forte iocd->stmf_obuf_nentries = n;
612fcf3ce44SJohn Forte ilu = stmf_state.stmf_ilulist;
613fcf3ce44SJohn Forte luid_list = (slist_lu_t *)obuf;
614fcf3ce44SJohn Forte for (i = 0; i < n; i++) {
615fcf3ce44SJohn Forte uint8_t *id;
616fcf3ce44SJohn Forte id = (uint8_t *)ilu->ilu_lu->lu_id;
617fcf3ce44SJohn Forte bcopy(id + 4, luid_list[i].lu_guid, 16);
618fcf3ce44SJohn Forte ilu = ilu->ilu_next;
619fcf3ce44SJohn Forte }
620fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
621fcf3ce44SJohn Forte break;
622fcf3ce44SJohn Forte
6238fe96085Stim szeto case STMF_IOCTL_VE_LU_LIST:
6248fe96085Stim szeto mutex_enter(&stmf_state.stmf_lock);
6258fe96085Stim szeto id_list = &stmf_state.stmf_luid_list;
6268fe96085Stim szeto n = min(id_list->id_count,
6278fe96085Stim szeto (iocd->stmf_obuf_size)/sizeof (slist_lu_t));
6288fe96085Stim szeto iocd->stmf_obuf_max_nentries = id_list->id_count;
6298fe96085Stim szeto iocd->stmf_obuf_nentries = n;
6308fe96085Stim szeto luid_list = (slist_lu_t *)obuf;
6318fe96085Stim szeto id_entry = id_list->idl_head;
6328fe96085Stim szeto for (i = 0; i < n; i++) {
6338fe96085Stim szeto bcopy(id_entry->id_data, luid_list[i].lu_guid, 16);
6348fe96085Stim szeto id_entry = id_entry->id_next;
6358fe96085Stim szeto }
6368fe96085Stim szeto mutex_exit(&stmf_state.stmf_lock);
6378fe96085Stim szeto break;
6388fe96085Stim szeto
639fcf3ce44SJohn Forte case STMF_IOCTL_TARGET_PORT_LIST:
640fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
641fcf3ce44SJohn Forte iocd->stmf_obuf_max_nentries = stmf_state.stmf_nlports;
642fcf3ce44SJohn Forte n = min(stmf_state.stmf_nlports,
643fcf3ce44SJohn Forte (iocd->stmf_obuf_size)/sizeof (slist_target_port_t));
644fcf3ce44SJohn Forte iocd->stmf_obuf_nentries = n;
645fcf3ce44SJohn Forte ilport = stmf_state.stmf_ilportlist;
646fcf3ce44SJohn Forte lportid_list = (slist_target_port_t *)obuf;
647fcf3ce44SJohn Forte for (i = 0; i < n; i++) {
648fcf3ce44SJohn Forte uint8_t *id;
649fcf3ce44SJohn Forte id = (uint8_t *)ilport->ilport_lport->lport_id;
650fcf3ce44SJohn Forte bcopy(id, lportid_list[i].target, id[3] + 4);
651fcf3ce44SJohn Forte ilport = ilport->ilport_next;
652fcf3ce44SJohn Forte }
653fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
654fcf3ce44SJohn Forte break;
655fcf3ce44SJohn Forte
656fcf3ce44SJohn Forte case STMF_IOCTL_SESSION_LIST:
657fcf3ce44SJohn Forte p_id = (uint8_t *)ibuf;
658fcf3ce44SJohn Forte if ((p_id == NULL) || (iocd->stmf_ibuf_size < 4) ||
659fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < (p_id[3] + 4))) {
660fcf3ce44SJohn Forte ret = EINVAL;
661fcf3ce44SJohn Forte break;
662fcf3ce44SJohn Forte }
663fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
664fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport; ilport =
665fcf3ce44SJohn Forte ilport->ilport_next) {
666fcf3ce44SJohn Forte uint8_t *id;
667fcf3ce44SJohn Forte id = (uint8_t *)ilport->ilport_lport->lport_id;
668fcf3ce44SJohn Forte if ((p_id[3] == id[3]) &&
669fcf3ce44SJohn Forte (bcmp(p_id + 4, id + 4, id[3]) == 0)) {
670fcf3ce44SJohn Forte break;
671fcf3ce44SJohn Forte }
672fcf3ce44SJohn Forte }
673fcf3ce44SJohn Forte if (ilport == NULL) {
674fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
675fcf3ce44SJohn Forte ret = ENOENT;
676fcf3ce44SJohn Forte break;
677fcf3ce44SJohn Forte }
678fcf3ce44SJohn Forte iocd->stmf_obuf_max_nentries = ilport->ilport_nsessions;
679fcf3ce44SJohn Forte n = min(ilport->ilport_nsessions,
680fcf3ce44SJohn Forte (iocd->stmf_obuf_size)/sizeof (slist_scsi_session_t));
681fcf3ce44SJohn Forte iocd->stmf_obuf_nentries = n;
682fcf3ce44SJohn Forte iss = ilport->ilport_ss_list;
683fcf3ce44SJohn Forte iss_list = (slist_scsi_session_t *)obuf;
684fcf3ce44SJohn Forte for (i = 0; i < n; i++) {
685fcf3ce44SJohn Forte uint8_t *id;
686fcf3ce44SJohn Forte id = (uint8_t *)iss->iss_ss->ss_rport_id;
687fcf3ce44SJohn Forte bcopy(id, iss_list[i].initiator, id[3] + 4);
688fcf3ce44SJohn Forte iss_list[i].creation_time = (uint32_t)
689fcf3ce44SJohn Forte iss->iss_creation_time;
690fcf3ce44SJohn Forte if (iss->iss_ss->ss_rport_alias) {
691fcf3ce44SJohn Forte (void) strncpy(iss_list[i].alias,
692fcf3ce44SJohn Forte iss->iss_ss->ss_rport_alias, 255);
693fcf3ce44SJohn Forte iss_list[i].alias[255] = 0;
694fcf3ce44SJohn Forte } else {
695fcf3ce44SJohn Forte iss_list[i].alias[0] = 0;
696fcf3ce44SJohn Forte }
697fcf3ce44SJohn Forte iss = iss->iss_next;
698fcf3ce44SJohn Forte }
699fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
700fcf3ce44SJohn Forte break;
701fcf3ce44SJohn Forte
702fcf3ce44SJohn Forte case STMF_IOCTL_GET_LU_PROPERTIES:
703fcf3ce44SJohn Forte p_id = (uint8_t *)ibuf;
704fcf3ce44SJohn Forte if ((iocd->stmf_ibuf_size < 16) ||
705fcf3ce44SJohn Forte (iocd->stmf_obuf_size < sizeof (sioc_lu_props_t)) ||
706fcf3ce44SJohn Forte (p_id[0] == 0)) {
707fcf3ce44SJohn Forte ret = EINVAL;
708fcf3ce44SJohn Forte break;
709fcf3ce44SJohn Forte }
710fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
711fcf3ce44SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
712fcf3ce44SJohn Forte if (bcmp(p_id, ilu->ilu_lu->lu_id->ident, 16) == 0)
713fcf3ce44SJohn Forte break;
714fcf3ce44SJohn Forte }
715fcf3ce44SJohn Forte if (ilu == NULL) {
716fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
717fcf3ce44SJohn Forte ret = ENOENT;
718fcf3ce44SJohn Forte break;
719fcf3ce44SJohn Forte }
720fcf3ce44SJohn Forte lup = (sioc_lu_props_t *)obuf;
721fcf3ce44SJohn Forte bcopy(ilu->ilu_lu->lu_id->ident, lup->lu_guid, 16);
722fcf3ce44SJohn Forte lup->lu_state = ilu->ilu_state & 0x0f;
723fcf3ce44SJohn Forte lup->lu_present = 1; /* XXX */
724fcf3ce44SJohn Forte (void) strncpy(lup->lu_provider_name,
725fcf3ce44SJohn Forte ilu->ilu_lu->lu_lp->lp_name, 255);
726fcf3ce44SJohn Forte lup->lu_provider_name[254] = 0;
727fcf3ce44SJohn Forte if (ilu->ilu_lu->lu_alias) {
728fcf3ce44SJohn Forte (void) strncpy(lup->lu_alias,
729fcf3ce44SJohn Forte ilu->ilu_lu->lu_alias, 255);
730fcf3ce44SJohn Forte lup->lu_alias[255] = 0;
731fcf3ce44SJohn Forte } else {
732fcf3ce44SJohn Forte lup->lu_alias[0] = 0;
733fcf3ce44SJohn Forte }
734fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
735fcf3ce44SJohn Forte break;
736fcf3ce44SJohn Forte
737fcf3ce44SJohn Forte case STMF_IOCTL_GET_TARGET_PORT_PROPERTIES:
738fcf3ce44SJohn Forte p_id = (uint8_t *)ibuf;
739fcf3ce44SJohn Forte if ((p_id == NULL) ||
740fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < (p_id[3] + 4)) ||
741fcf3ce44SJohn Forte (iocd->stmf_obuf_size <
742fcf3ce44SJohn Forte sizeof (sioc_target_port_props_t))) {
743fcf3ce44SJohn Forte ret = EINVAL;
744fcf3ce44SJohn Forte break;
745fcf3ce44SJohn Forte }
746fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
747fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport;
748fcf3ce44SJohn Forte ilport = ilport->ilport_next) {
749fcf3ce44SJohn Forte uint8_t *id;
750fcf3ce44SJohn Forte id = (uint8_t *)ilport->ilport_lport->lport_id;
751fcf3ce44SJohn Forte if ((p_id[3] == id[3]) &&
752fcf3ce44SJohn Forte (bcmp(p_id+4, id+4, id[3]) == 0))
753fcf3ce44SJohn Forte break;
754fcf3ce44SJohn Forte }
755fcf3ce44SJohn Forte if (ilport == NULL) {
756fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
757fcf3ce44SJohn Forte ret = ENOENT;
758fcf3ce44SJohn Forte break;
759fcf3ce44SJohn Forte }
760fcf3ce44SJohn Forte lportp = (sioc_target_port_props_t *)obuf;
761fcf3ce44SJohn Forte bcopy(ilport->ilport_lport->lport_id, lportp->tgt_id,
762fcf3ce44SJohn Forte ilport->ilport_lport->lport_id->ident_length + 4);
763fcf3ce44SJohn Forte lportp->tgt_state = ilport->ilport_state & 0x0f;
764fcf3ce44SJohn Forte lportp->tgt_present = 1; /* XXX */
765fcf3ce44SJohn Forte (void) strncpy(lportp->tgt_provider_name,
766fcf3ce44SJohn Forte ilport->ilport_lport->lport_pp->pp_name, 255);
767fcf3ce44SJohn Forte lportp->tgt_provider_name[254] = 0;
768fcf3ce44SJohn Forte if (ilport->ilport_lport->lport_alias) {
769fcf3ce44SJohn Forte (void) strncpy(lportp->tgt_alias,
770fcf3ce44SJohn Forte ilport->ilport_lport->lport_alias, 255);
771fcf3ce44SJohn Forte lportp->tgt_alias[255] = 0;
772fcf3ce44SJohn Forte } else {
773fcf3ce44SJohn Forte lportp->tgt_alias[0] = 0;
774fcf3ce44SJohn Forte }
775fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
776fcf3ce44SJohn Forte break;
777fcf3ce44SJohn Forte
778fcf3ce44SJohn Forte case STMF_IOCTL_SET_STMF_STATE:
779fcf3ce44SJohn Forte if ((ibuf == NULL) ||
780fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
781fcf3ce44SJohn Forte ret = EINVAL;
782fcf3ce44SJohn Forte break;
783fcf3ce44SJohn Forte }
784fcf3ce44SJohn Forte ret = stmf_set_stmf_state((stmf_state_desc_t *)ibuf);
785fcf3ce44SJohn Forte break;
786fcf3ce44SJohn Forte
787fcf3ce44SJohn Forte case STMF_IOCTL_GET_STMF_STATE:
788fcf3ce44SJohn Forte if ((obuf == NULL) ||
789fcf3ce44SJohn Forte (iocd->stmf_obuf_size < sizeof (stmf_state_desc_t))) {
790fcf3ce44SJohn Forte ret = EINVAL;
791fcf3ce44SJohn Forte break;
792fcf3ce44SJohn Forte }
793fcf3ce44SJohn Forte ret = stmf_get_stmf_state((stmf_state_desc_t *)obuf);
794fcf3ce44SJohn Forte break;
795fcf3ce44SJohn Forte
79645039663SJohn Forte case STMF_IOCTL_SET_ALUA_STATE:
79745039663SJohn Forte if ((ibuf == NULL) ||
79845039663SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_alua_state_desc_t))) {
79945039663SJohn Forte ret = EINVAL;
80045039663SJohn Forte break;
80145039663SJohn Forte }
80245039663SJohn Forte ret = stmf_set_alua_state((stmf_alua_state_desc_t *)ibuf);
80345039663SJohn Forte break;
80445039663SJohn Forte
80545039663SJohn Forte case STMF_IOCTL_GET_ALUA_STATE:
80645039663SJohn Forte if ((obuf == NULL) ||
80745039663SJohn Forte (iocd->stmf_obuf_size < sizeof (stmf_alua_state_desc_t))) {
80845039663SJohn Forte ret = EINVAL;
80945039663SJohn Forte break;
81045039663SJohn Forte }
81145039663SJohn Forte stmf_get_alua_state((stmf_alua_state_desc_t *)obuf);
81245039663SJohn Forte break;
81345039663SJohn Forte
814fcf3ce44SJohn Forte case STMF_IOCTL_SET_LU_STATE:
815fcf3ce44SJohn Forte ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
816fcf3ce44SJohn Forte ssi.st_additional_info = NULL;
817fcf3ce44SJohn Forte std = (stmf_state_desc_t *)ibuf;
818fcf3ce44SJohn Forte if ((ibuf == NULL) ||
819fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
820fcf3ce44SJohn Forte ret = EINVAL;
821fcf3ce44SJohn Forte break;
822fcf3ce44SJohn Forte }
823fcf3ce44SJohn Forte p_id = std->ident;
824fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
825fcf3ce44SJohn Forte if (stmf_state.stmf_inventory_locked) {
826fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
827fcf3ce44SJohn Forte ret = EBUSY;
828fcf3ce44SJohn Forte break;
829fcf3ce44SJohn Forte }
830fcf3ce44SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
831fcf3ce44SJohn Forte if (bcmp(p_id, ilu->ilu_lu->lu_id->ident, 16) == 0)
832fcf3ce44SJohn Forte break;
833fcf3ce44SJohn Forte }
834fcf3ce44SJohn Forte if (ilu == NULL) {
835fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
836fcf3ce44SJohn Forte ret = ENOENT;
837fcf3ce44SJohn Forte break;
838fcf3ce44SJohn Forte }
839fcf3ce44SJohn Forte stmf_state.stmf_inventory_locked = 1;
840fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
841fcf3ce44SJohn Forte cmd = (std->state == STMF_STATE_ONLINE) ? STMF_CMD_LU_ONLINE :
842fcf3ce44SJohn Forte STMF_CMD_LU_OFFLINE;
843fcf3ce44SJohn Forte ctl_ret = stmf_ctl(cmd, (void *)ilu->ilu_lu, &ssi);
844fcf3ce44SJohn Forte if (ctl_ret == STMF_ALREADY)
845fcf3ce44SJohn Forte ret = 0;
8464f486358SNattuvetty Bhavyan else if (ctl_ret == STMF_BUSY)
8474f486358SNattuvetty Bhavyan ret = EBUSY;
848fcf3ce44SJohn Forte else if (ctl_ret != STMF_SUCCESS)
849fcf3ce44SJohn Forte ret = EIO;
850fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
851fcf3ce44SJohn Forte stmf_state.stmf_inventory_locked = 0;
852fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
853fcf3ce44SJohn Forte break;
854fcf3ce44SJohn Forte
8554b31676fSsrivijitha dugganapalli case STMF_IOCTL_SET_STMF_PROPS:
8564b31676fSsrivijitha dugganapalli if ((ibuf == NULL) ||
8574b31676fSsrivijitha dugganapalli (iocd->stmf_ibuf_size < sizeof (stmf_set_props_t))) {
8584b31676fSsrivijitha dugganapalli ret = EINVAL;
8594b31676fSsrivijitha dugganapalli break;
8604b31676fSsrivijitha dugganapalli }
8614b31676fSsrivijitha dugganapalli stmf_set_props = (stmf_set_props_t *)ibuf;
8624b31676fSsrivijitha dugganapalli mutex_enter(&stmf_state.stmf_lock);
8634b31676fSsrivijitha dugganapalli if ((stmf_set_props->default_lu_state_value ==
8644b31676fSsrivijitha dugganapalli STMF_STATE_OFFLINE) ||
8654b31676fSsrivijitha dugganapalli (stmf_set_props->default_lu_state_value ==
8664b31676fSsrivijitha dugganapalli STMF_STATE_ONLINE)) {
8674b31676fSsrivijitha dugganapalli stmf_state.stmf_default_lu_state =
8684b31676fSsrivijitha dugganapalli stmf_set_props->default_lu_state_value;
8694b31676fSsrivijitha dugganapalli }
8704b31676fSsrivijitha dugganapalli if ((stmf_set_props->default_target_state_value ==
8714b31676fSsrivijitha dugganapalli STMF_STATE_OFFLINE) ||
8724b31676fSsrivijitha dugganapalli (stmf_set_props->default_target_state_value ==
8734b31676fSsrivijitha dugganapalli STMF_STATE_ONLINE)) {
8744b31676fSsrivijitha dugganapalli stmf_state.stmf_default_lport_state =
8754b31676fSsrivijitha dugganapalli stmf_set_props->default_target_state_value;
8764b31676fSsrivijitha dugganapalli }
8774b31676fSsrivijitha dugganapalli
8784b31676fSsrivijitha dugganapalli mutex_exit(&stmf_state.stmf_lock);
8794b31676fSsrivijitha dugganapalli break;
8804b31676fSsrivijitha dugganapalli
881fcf3ce44SJohn Forte case STMF_IOCTL_SET_TARGET_PORT_STATE:
882fcf3ce44SJohn Forte ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
883fcf3ce44SJohn Forte ssi.st_additional_info = NULL;
884fcf3ce44SJohn Forte std = (stmf_state_desc_t *)ibuf;
885fcf3ce44SJohn Forte if ((ibuf == NULL) ||
886fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
887fcf3ce44SJohn Forte ret = EINVAL;
888fcf3ce44SJohn Forte break;
889fcf3ce44SJohn Forte }
890fcf3ce44SJohn Forte p_id = std->ident;
891fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
892fcf3ce44SJohn Forte if (stmf_state.stmf_inventory_locked) {
893fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
894fcf3ce44SJohn Forte ret = EBUSY;
895fcf3ce44SJohn Forte break;
896fcf3ce44SJohn Forte }
897fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport;
898fcf3ce44SJohn Forte ilport = ilport->ilport_next) {
899fcf3ce44SJohn Forte uint8_t *id;
900fcf3ce44SJohn Forte id = (uint8_t *)ilport->ilport_lport->lport_id;
901fcf3ce44SJohn Forte if ((id[3] == p_id[3]) &&
902fcf3ce44SJohn Forte (bcmp(id+4, p_id+4, id[3]) == 0)) {
903fcf3ce44SJohn Forte break;
904fcf3ce44SJohn Forte }
905fcf3ce44SJohn Forte }
906fcf3ce44SJohn Forte if (ilport == NULL) {
907fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
908fcf3ce44SJohn Forte ret = ENOENT;
909fcf3ce44SJohn Forte break;
910fcf3ce44SJohn Forte }
911fcf3ce44SJohn Forte stmf_state.stmf_inventory_locked = 1;
912fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
913fcf3ce44SJohn Forte cmd = (std->state == STMF_STATE_ONLINE) ?
914fcf3ce44SJohn Forte STMF_CMD_LPORT_ONLINE : STMF_CMD_LPORT_OFFLINE;
915fcf3ce44SJohn Forte ctl_ret = stmf_ctl(cmd, (void *)ilport->ilport_lport, &ssi);
916fcf3ce44SJohn Forte if (ctl_ret == STMF_ALREADY)
917fcf3ce44SJohn Forte ret = 0;
9184f486358SNattuvetty Bhavyan else if (ctl_ret == STMF_BUSY)
9194f486358SNattuvetty Bhavyan ret = EBUSY;
920fcf3ce44SJohn Forte else if (ctl_ret != STMF_SUCCESS)
921fcf3ce44SJohn Forte ret = EIO;
922fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
923fcf3ce44SJohn Forte stmf_state.stmf_inventory_locked = 0;
924fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
925fcf3ce44SJohn Forte break;
926fcf3ce44SJohn Forte
927fcf3ce44SJohn Forte case STMF_IOCTL_ADD_HG_ENTRY:
928fcf3ce44SJohn Forte idtype = STMF_ID_TYPE_HOST;
929fcf3ce44SJohn Forte /* FALLTHROUGH */
930fcf3ce44SJohn Forte case STMF_IOCTL_ADD_TG_ENTRY:
931fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
932fcf3ce44SJohn Forte ret = EACCES;
933fcf3ce44SJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
934fcf3ce44SJohn Forte break;
935fcf3ce44SJohn Forte }
936fcf3ce44SJohn Forte if (cmd == STMF_IOCTL_ADD_TG_ENTRY) {
937fcf3ce44SJohn Forte idtype = STMF_ID_TYPE_TARGET;
938fcf3ce44SJohn Forte }
939fcf3ce44SJohn Forte grp_entry = (stmf_group_op_data_t *)ibuf;
940fcf3ce44SJohn Forte if ((ibuf == NULL) ||
941fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_op_data_t))) {
942fcf3ce44SJohn Forte ret = EINVAL;
943fcf3ce44SJohn Forte break;
944fcf3ce44SJohn Forte }
945fcf3ce44SJohn Forte if (grp_entry->group.name[0] == '*') {
946fcf3ce44SJohn Forte ret = EINVAL;
947fcf3ce44SJohn Forte break; /* not allowed */
948fcf3ce44SJohn Forte }
949fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
950fcf3ce44SJohn Forte ret = stmf_add_group_member(grp_entry->group.name,
951fcf3ce44SJohn Forte grp_entry->group.name_size,
952fcf3ce44SJohn Forte grp_entry->ident + 4,
953fcf3ce44SJohn Forte grp_entry->ident[3],
954fcf3ce44SJohn Forte idtype,
955fcf3ce44SJohn Forte &iocd->stmf_error);
956fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
957fcf3ce44SJohn Forte break;
958fcf3ce44SJohn Forte case STMF_IOCTL_REMOVE_HG_ENTRY:
959fcf3ce44SJohn Forte idtype = STMF_ID_TYPE_HOST;
960fcf3ce44SJohn Forte /* FALLTHROUGH */
961fcf3ce44SJohn Forte case STMF_IOCTL_REMOVE_TG_ENTRY:
962fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
963fcf3ce44SJohn Forte ret = EACCES;
964fcf3ce44SJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
965fcf3ce44SJohn Forte break;
966fcf3ce44SJohn Forte }
967fcf3ce44SJohn Forte if (cmd == STMF_IOCTL_REMOVE_TG_ENTRY) {
968fcf3ce44SJohn Forte idtype = STMF_ID_TYPE_TARGET;
969fcf3ce44SJohn Forte }
970fcf3ce44SJohn Forte grp_entry = (stmf_group_op_data_t *)ibuf;
971fcf3ce44SJohn Forte if ((ibuf == NULL) ||
972fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_op_data_t))) {
973fcf3ce44SJohn Forte ret = EINVAL;
974fcf3ce44SJohn Forte break;
975fcf3ce44SJohn Forte }
976fcf3ce44SJohn Forte if (grp_entry->group.name[0] == '*') {
977fcf3ce44SJohn Forte ret = EINVAL;
978fcf3ce44SJohn Forte break; /* not allowed */
979fcf3ce44SJohn Forte }
980fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
981fcf3ce44SJohn Forte ret = stmf_remove_group_member(grp_entry->group.name,
982fcf3ce44SJohn Forte grp_entry->group.name_size,
983fcf3ce44SJohn Forte grp_entry->ident + 4,
984fcf3ce44SJohn Forte grp_entry->ident[3],
985fcf3ce44SJohn Forte idtype,
986fcf3ce44SJohn Forte &iocd->stmf_error);
987fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
988fcf3ce44SJohn Forte break;
989fcf3ce44SJohn Forte case STMF_IOCTL_CREATE_HOST_GROUP:
990fcf3ce44SJohn Forte idtype = STMF_ID_TYPE_HOST_GROUP;
991fcf3ce44SJohn Forte /* FALLTHROUGH */
992fcf3ce44SJohn Forte case STMF_IOCTL_CREATE_TARGET_GROUP:
993fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
994fcf3ce44SJohn Forte ret = EACCES;
995fcf3ce44SJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
996fcf3ce44SJohn Forte break;
997fcf3ce44SJohn Forte }
998fcf3ce44SJohn Forte grpname = (stmf_group_name_t *)ibuf;
999fcf3ce44SJohn Forte
1000fcf3ce44SJohn Forte if (cmd == STMF_IOCTL_CREATE_TARGET_GROUP)
1001fcf3ce44SJohn Forte idtype = STMF_ID_TYPE_TARGET_GROUP;
1002fcf3ce44SJohn Forte if ((ibuf == NULL) ||
1003fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
1004fcf3ce44SJohn Forte ret = EINVAL;
1005fcf3ce44SJohn Forte break;
1006fcf3ce44SJohn Forte }
1007fcf3ce44SJohn Forte if (grpname->name[0] == '*') {
1008fcf3ce44SJohn Forte ret = EINVAL;
1009fcf3ce44SJohn Forte break; /* not allowed */
1010fcf3ce44SJohn Forte }
1011fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1012fcf3ce44SJohn Forte ret = stmf_add_group(grpname->name,
1013fcf3ce44SJohn Forte grpname->name_size, idtype, &iocd->stmf_error);
1014fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1015fcf3ce44SJohn Forte break;
1016fcf3ce44SJohn Forte case STMF_IOCTL_REMOVE_HOST_GROUP:
1017fcf3ce44SJohn Forte idtype = STMF_ID_TYPE_HOST_GROUP;
1018fcf3ce44SJohn Forte /* FALLTHROUGH */
1019fcf3ce44SJohn Forte case STMF_IOCTL_REMOVE_TARGET_GROUP:
1020fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1021fcf3ce44SJohn Forte ret = EACCES;
1022fcf3ce44SJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1023fcf3ce44SJohn Forte break;
1024fcf3ce44SJohn Forte }
1025fcf3ce44SJohn Forte grpname = (stmf_group_name_t *)ibuf;
1026fcf3ce44SJohn Forte if (cmd == STMF_IOCTL_REMOVE_TARGET_GROUP)
1027fcf3ce44SJohn Forte idtype = STMF_ID_TYPE_TARGET_GROUP;
1028fcf3ce44SJohn Forte if ((ibuf == NULL) ||
1029fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
1030fcf3ce44SJohn Forte ret = EINVAL;
1031fcf3ce44SJohn Forte break;
1032fcf3ce44SJohn Forte }
1033fcf3ce44SJohn Forte if (grpname->name[0] == '*') {
1034fcf3ce44SJohn Forte ret = EINVAL;
1035fcf3ce44SJohn Forte break; /* not allowed */
1036fcf3ce44SJohn Forte }
1037fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1038fcf3ce44SJohn Forte ret = stmf_remove_group(grpname->name,
1039fcf3ce44SJohn Forte grpname->name_size, idtype, &iocd->stmf_error);
1040fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1041fcf3ce44SJohn Forte break;
104263ed874aStim szeto case STMF_IOCTL_VALIDATE_VIEW:
1043fcf3ce44SJohn Forte case STMF_IOCTL_ADD_VIEW_ENTRY:
1044fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1045fcf3ce44SJohn Forte ret = EACCES;
1046fcf3ce44SJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1047fcf3ce44SJohn Forte break;
1048fcf3ce44SJohn Forte }
1049fcf3ce44SJohn Forte ve = (stmf_view_op_entry_t *)ibuf;
1050fcf3ce44SJohn Forte if ((ibuf == NULL) ||
1051fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_view_op_entry_t))) {
1052fcf3ce44SJohn Forte ret = EINVAL;
1053fcf3ce44SJohn Forte break;
1054fcf3ce44SJohn Forte }
1055fcf3ce44SJohn Forte if (!ve->ve_lu_number_valid)
1056fcf3ce44SJohn Forte ve->ve_lu_nbr[2] = 0xFF;
1057fcf3ce44SJohn Forte if (ve->ve_all_hosts) {
1058fcf3ce44SJohn Forte ve->ve_host_group.name[0] = '*';
1059fcf3ce44SJohn Forte ve->ve_host_group.name_size = 1;
1060fcf3ce44SJohn Forte }
1061fcf3ce44SJohn Forte if (ve->ve_all_targets) {
1062fcf3ce44SJohn Forte ve->ve_target_group.name[0] = '*';
1063fcf3ce44SJohn Forte ve->ve_target_group.name_size = 1;
1064fcf3ce44SJohn Forte }
1065fcf3ce44SJohn Forte if (ve->ve_ndx_valid)
1066fcf3ce44SJohn Forte veid = ve->ve_ndx;
1067fcf3ce44SJohn Forte else
1068fcf3ce44SJohn Forte veid = 0xffffffff;
1069fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
107063ed874aStim szeto if (cmd == STMF_IOCTL_ADD_VIEW_ENTRY) {
1071fcf3ce44SJohn Forte ret = stmf_add_ve(ve->ve_host_group.name,
1072fcf3ce44SJohn Forte ve->ve_host_group.name_size,
1073fcf3ce44SJohn Forte ve->ve_target_group.name,
1074fcf3ce44SJohn Forte ve->ve_target_group.name_size,
1075fcf3ce44SJohn Forte ve->ve_guid,
1076fcf3ce44SJohn Forte &veid,
1077fcf3ce44SJohn Forte ve->ve_lu_nbr,
1078fcf3ce44SJohn Forte &iocd->stmf_error);
107963ed874aStim szeto } else { /* STMF_IOCTL_VALIDATE_VIEW */
108063ed874aStim szeto ret = stmf_validate_lun_ve(ve->ve_host_group.name,
108163ed874aStim szeto ve->ve_host_group.name_size,
108263ed874aStim szeto ve->ve_target_group.name,
108363ed874aStim szeto ve->ve_target_group.name_size,
108463ed874aStim szeto ve->ve_lu_nbr,
108563ed874aStim szeto &iocd->stmf_error);
108663ed874aStim szeto }
1087fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1088fcf3ce44SJohn Forte if (ret == 0 &&
1089fcf3ce44SJohn Forte (!ve->ve_ndx_valid || !ve->ve_lu_number_valid) &&
1090fcf3ce44SJohn Forte iocd->stmf_obuf_size >= sizeof (stmf_view_op_entry_t)) {
1091fcf3ce44SJohn Forte stmf_view_op_entry_t *ve_ret =
1092fcf3ce44SJohn Forte (stmf_view_op_entry_t *)obuf;
1093fcf3ce44SJohn Forte iocd->stmf_obuf_nentries = 1;
1094fcf3ce44SJohn Forte iocd->stmf_obuf_max_nentries = 1;
1095fcf3ce44SJohn Forte if (!ve->ve_ndx_valid) {
1096fcf3ce44SJohn Forte ve_ret->ve_ndx = veid;
1097fcf3ce44SJohn Forte ve_ret->ve_ndx_valid = 1;
1098fcf3ce44SJohn Forte }
1099fcf3ce44SJohn Forte if (!ve->ve_lu_number_valid) {
1100fcf3ce44SJohn Forte ve_ret->ve_lu_number_valid = 1;
1101fcf3ce44SJohn Forte bcopy(ve->ve_lu_nbr, ve_ret->ve_lu_nbr, 8);
1102fcf3ce44SJohn Forte }
1103fcf3ce44SJohn Forte }
1104fcf3ce44SJohn Forte break;
1105fcf3ce44SJohn Forte case STMF_IOCTL_REMOVE_VIEW_ENTRY:
1106fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1107fcf3ce44SJohn Forte ret = EACCES;
1108fcf3ce44SJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1109fcf3ce44SJohn Forte break;
1110fcf3ce44SJohn Forte }
1111fcf3ce44SJohn Forte ve = (stmf_view_op_entry_t *)ibuf;
1112fcf3ce44SJohn Forte if ((ibuf == NULL) ||
1113fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_view_op_entry_t))) {
1114fcf3ce44SJohn Forte ret = EINVAL;
1115fcf3ce44SJohn Forte break;
1116fcf3ce44SJohn Forte }
1117fcf3ce44SJohn Forte if (!ve->ve_ndx_valid) {
1118fcf3ce44SJohn Forte ret = EINVAL;
1119fcf3ce44SJohn Forte break;
1120fcf3ce44SJohn Forte }
1121fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1122fcf3ce44SJohn Forte ret = stmf_remove_ve_by_id(ve->ve_guid, ve->ve_ndx,
1123fcf3ce44SJohn Forte &iocd->stmf_error);
1124fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1125fcf3ce44SJohn Forte break;
1126fcf3ce44SJohn Forte case STMF_IOCTL_GET_HG_LIST:
1127fcf3ce44SJohn Forte id_list = &stmf_state.stmf_hg_list;
1128fcf3ce44SJohn Forte /* FALLTHROUGH */
1129fcf3ce44SJohn Forte case STMF_IOCTL_GET_TG_LIST:
1130fcf3ce44SJohn Forte if (cmd == STMF_IOCTL_GET_TG_LIST)
1131fcf3ce44SJohn Forte id_list = &stmf_state.stmf_tg_list;
1132fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1133fcf3ce44SJohn Forte iocd->stmf_obuf_max_nentries = id_list->id_count;
1134fcf3ce44SJohn Forte n = min(id_list->id_count,
1135fcf3ce44SJohn Forte (iocd->stmf_obuf_size)/sizeof (stmf_group_name_t));
1136fcf3ce44SJohn Forte iocd->stmf_obuf_nentries = n;
1137fcf3ce44SJohn Forte id_entry = id_list->idl_head;
1138fcf3ce44SJohn Forte grpname = (stmf_group_name_t *)obuf;
1139fcf3ce44SJohn Forte for (i = 0; i < n; i++) {
11408fe96085Stim szeto if (id_entry->id_data[0] == '*') {
11418fe96085Stim szeto if (iocd->stmf_obuf_nentries > 0) {
11428fe96085Stim szeto iocd->stmf_obuf_nentries--;
11438fe96085Stim szeto }
11448fe96085Stim szeto id_entry = id_entry->id_next;
11458fe96085Stim szeto continue;
11468fe96085Stim szeto }
11478fe96085Stim szeto grpname->name_size = id_entry->id_data_size;
11488fe96085Stim szeto bcopy(id_entry->id_data, grpname->name,
1149fcf3ce44SJohn Forte id_entry->id_data_size);
11508fe96085Stim szeto grpname++;
1151fcf3ce44SJohn Forte id_entry = id_entry->id_next;
1152fcf3ce44SJohn Forte }
1153fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1154fcf3ce44SJohn Forte break;
1155fcf3ce44SJohn Forte case STMF_IOCTL_GET_HG_ENTRIES:
1156fcf3ce44SJohn Forte id_list = &stmf_state.stmf_hg_list;
1157fcf3ce44SJohn Forte /* FALLTHROUGH */
1158fcf3ce44SJohn Forte case STMF_IOCTL_GET_TG_ENTRIES:
1159fcf3ce44SJohn Forte grpname = (stmf_group_name_t *)ibuf;
1160fcf3ce44SJohn Forte if ((ibuf == NULL) ||
1161fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
1162fcf3ce44SJohn Forte ret = EINVAL;
1163fcf3ce44SJohn Forte break;
1164fcf3ce44SJohn Forte }
1165fcf3ce44SJohn Forte if (cmd == STMF_IOCTL_GET_TG_ENTRIES) {
1166fcf3ce44SJohn Forte id_list = &stmf_state.stmf_tg_list;
1167fcf3ce44SJohn Forte }
1168fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1169fcf3ce44SJohn Forte id_entry = stmf_lookup_id(id_list, grpname->name_size,
1170fcf3ce44SJohn Forte grpname->name);
1171fcf3ce44SJohn Forte if (!id_entry)
1172fcf3ce44SJohn Forte ret = ENODEV;
1173fcf3ce44SJohn Forte else {
1174fcf3ce44SJohn Forte stmf_ge_ident_t *grp_entry;
1175fcf3ce44SJohn Forte id_list = (stmf_id_list_t *)id_entry->id_impl_specific;
1176fcf3ce44SJohn Forte iocd->stmf_obuf_max_nentries = id_list->id_count;
1177fcf3ce44SJohn Forte n = min(id_list->id_count,
1178fcf3ce44SJohn Forte iocd->stmf_obuf_size/sizeof (stmf_ge_ident_t));
1179fcf3ce44SJohn Forte iocd->stmf_obuf_nentries = n;
1180fcf3ce44SJohn Forte id_entry = id_list->idl_head;
1181fcf3ce44SJohn Forte grp_entry = (stmf_ge_ident_t *)obuf;
1182fcf3ce44SJohn Forte for (i = 0; i < n; i++) {
11838fe96085Stim szeto bcopy(id_entry->id_data, grp_entry->ident,
1184fcf3ce44SJohn Forte id_entry->id_data_size);
11858fe96085Stim szeto grp_entry->ident_size = id_entry->id_data_size;
1186fcf3ce44SJohn Forte id_entry = id_entry->id_next;
11878fe96085Stim szeto grp_entry++;
1188fcf3ce44SJohn Forte }
1189fcf3ce44SJohn Forte }
1190fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1191fcf3ce44SJohn Forte break;
11928fe96085Stim szeto
1193fcf3ce44SJohn Forte case STMF_IOCTL_GET_VE_LIST:
1194fcf3ce44SJohn Forte n = iocd->stmf_obuf_size/sizeof (stmf_view_op_entry_t);
1195fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1196fcf3ce44SJohn Forte ve = (stmf_view_op_entry_t *)obuf;
11978fe96085Stim szeto for (id_entry = stmf_state.stmf_luid_list.idl_head;
11988fe96085Stim szeto id_entry; id_entry = id_entry->id_next) {
11998fe96085Stim szeto for (view_entry = (stmf_view_entry_t *)
12008fe96085Stim szeto id_entry->id_impl_specific; view_entry;
12018fe96085Stim szeto view_entry = view_entry->ve_next) {
12028fe96085Stim szeto iocd->stmf_obuf_max_nentries++;
12038fe96085Stim szeto if (iocd->stmf_obuf_nentries >= n)
12048fe96085Stim szeto continue;
1205fcf3ce44SJohn Forte ve->ve_ndx_valid = 1;
1206fcf3ce44SJohn Forte ve->ve_ndx = view_entry->ve_id;
1207fcf3ce44SJohn Forte ve->ve_lu_number_valid = 1;
1208fcf3ce44SJohn Forte bcopy(view_entry->ve_lun, ve->ve_lu_nbr, 8);
1209fcf3ce44SJohn Forte bcopy(view_entry->ve_luid->id_data, ve->ve_guid,
1210fcf3ce44SJohn Forte view_entry->ve_luid->id_data_size);
12118fe96085Stim szeto if (view_entry->ve_hg->id_data[0] == '*') {
1212fcf3ce44SJohn Forte ve->ve_all_hosts = 1;
12138fe96085Stim szeto } else {
1214fcf3ce44SJohn Forte bcopy(view_entry->ve_hg->id_data,
1215fcf3ce44SJohn Forte ve->ve_host_group.name,
1216fcf3ce44SJohn Forte view_entry->ve_hg->id_data_size);
12178fe96085Stim szeto ve->ve_host_group.name_size =
12188fe96085Stim szeto view_entry->ve_hg->id_data_size;
12198fe96085Stim szeto }
12208fe96085Stim szeto
12218fe96085Stim szeto if (view_entry->ve_tg->id_data[0] == '*') {
1222fcf3ce44SJohn Forte ve->ve_all_targets = 1;
12238fe96085Stim szeto } else {
1224fcf3ce44SJohn Forte bcopy(view_entry->ve_tg->id_data,
1225fcf3ce44SJohn Forte ve->ve_target_group.name,
1226fcf3ce44SJohn Forte view_entry->ve_tg->id_data_size);
12278fe96085Stim szeto ve->ve_target_group.name_size =
12288fe96085Stim szeto view_entry->ve_tg->id_data_size;
12298fe96085Stim szeto }
12308fe96085Stim szeto ve++;
1231fcf3ce44SJohn Forte iocd->stmf_obuf_nentries++;
12328fe96085Stim szeto }
12338fe96085Stim szeto }
12348fe96085Stim szeto mutex_exit(&stmf_state.stmf_lock);
12358fe96085Stim szeto break;
12368fe96085Stim szeto
12378fe96085Stim szeto case STMF_IOCTL_LU_VE_LIST:
12388fe96085Stim szeto p_id = (uint8_t *)ibuf;
12398fe96085Stim szeto if ((iocd->stmf_ibuf_size != 16) ||
12408fe96085Stim szeto (iocd->stmf_obuf_size < sizeof (stmf_view_op_entry_t))) {
12418fe96085Stim szeto ret = EINVAL;
1242fcf3ce44SJohn Forte break;
1243fcf3ce44SJohn Forte }
12448fe96085Stim szeto
12458fe96085Stim szeto n = iocd->stmf_obuf_size/sizeof (stmf_view_op_entry_t);
12468fe96085Stim szeto mutex_enter(&stmf_state.stmf_lock);
12478fe96085Stim szeto ve = (stmf_view_op_entry_t *)obuf;
12488fe96085Stim szeto for (id_entry = stmf_state.stmf_luid_list.idl_head;
12498fe96085Stim szeto id_entry; id_entry = id_entry->id_next) {
12508fe96085Stim szeto if (bcmp(id_entry->id_data, p_id, 16) != 0)
12518fe96085Stim szeto continue;
12528fe96085Stim szeto for (view_entry = (stmf_view_entry_t *)
12538fe96085Stim szeto id_entry->id_impl_specific; view_entry;
12548fe96085Stim szeto view_entry = view_entry->ve_next) {
12558fe96085Stim szeto iocd->stmf_obuf_max_nentries++;
1256fcf3ce44SJohn Forte if (iocd->stmf_obuf_nentries >= n)
12578fe96085Stim szeto continue;
12588fe96085Stim szeto ve->ve_ndx_valid = 1;
12598fe96085Stim szeto ve->ve_ndx = view_entry->ve_id;
12608fe96085Stim szeto ve->ve_lu_number_valid = 1;
12618fe96085Stim szeto bcopy(view_entry->ve_lun, ve->ve_lu_nbr, 8);
12628fe96085Stim szeto bcopy(view_entry->ve_luid->id_data, ve->ve_guid,
12638fe96085Stim szeto view_entry->ve_luid->id_data_size);
12648fe96085Stim szeto if (view_entry->ve_hg->id_data[0] == '*') {
12658fe96085Stim szeto ve->ve_all_hosts = 1;
12668fe96085Stim szeto } else {
12678fe96085Stim szeto bcopy(view_entry->ve_hg->id_data,
12688fe96085Stim szeto ve->ve_host_group.name,
12698fe96085Stim szeto view_entry->ve_hg->id_data_size);
12708fe96085Stim szeto ve->ve_host_group.name_size =
12718fe96085Stim szeto view_entry->ve_hg->id_data_size;
12728fe96085Stim szeto }
12738fe96085Stim szeto
12748fe96085Stim szeto if (view_entry->ve_tg->id_data[0] == '*') {
12758fe96085Stim szeto ve->ve_all_targets = 1;
12768fe96085Stim szeto } else {
12778fe96085Stim szeto bcopy(view_entry->ve_tg->id_data,
12788fe96085Stim szeto ve->ve_target_group.name,
12798fe96085Stim szeto view_entry->ve_tg->id_data_size);
12808fe96085Stim szeto ve->ve_target_group.name_size =
12818fe96085Stim szeto view_entry->ve_tg->id_data_size;
12828fe96085Stim szeto }
12838fe96085Stim szeto ve++;
12848fe96085Stim szeto iocd->stmf_obuf_nentries++;
12858fe96085Stim szeto }
1286fcf3ce44SJohn Forte break;
1287fcf3ce44SJohn Forte }
1288fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1289fcf3ce44SJohn Forte break;
12908fe96085Stim szeto
1291fcf3ce44SJohn Forte case STMF_IOCTL_LOAD_PP_DATA:
1292fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1293fcf3ce44SJohn Forte ret = EACCES;
1294fcf3ce44SJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1295fcf3ce44SJohn Forte break;
1296fcf3ce44SJohn Forte }
1297fcf3ce44SJohn Forte ppi = (stmf_ppioctl_data_t *)ibuf;
1298fcf3ce44SJohn Forte if ((ppi == NULL) ||
1299fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
1300fcf3ce44SJohn Forte ret = EINVAL;
1301fcf3ce44SJohn Forte break;
1302fcf3ce44SJohn Forte }
13038fe96085Stim szeto /* returned token */
13048fe96085Stim szeto ppi_token = (uint64_t *)obuf;
13058fe96085Stim szeto if ((ppi_token == NULL) ||
13068fe96085Stim szeto (iocd->stmf_obuf_size < sizeof (uint64_t))) {
13078fe96085Stim szeto ret = EINVAL;
13088fe96085Stim szeto break;
13098fe96085Stim szeto }
13108fe96085Stim szeto ret = stmf_load_ppd_ioctl(ppi, ppi_token, &iocd->stmf_error);
13118fe96085Stim szeto break;
13128fe96085Stim szeto
13138fe96085Stim szeto case STMF_IOCTL_GET_PP_DATA:
13148fe96085Stim szeto if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
13158fe96085Stim szeto ret = EACCES;
13168fe96085Stim szeto iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
13178fe96085Stim szeto break;
13188fe96085Stim szeto }
13198fe96085Stim szeto ppi = (stmf_ppioctl_data_t *)ibuf;
13208fe96085Stim szeto if (ppi == NULL ||
13218fe96085Stim szeto (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
13228fe96085Stim szeto ret = EINVAL;
13238fe96085Stim szeto break;
13248fe96085Stim szeto }
13258fe96085Stim szeto ppi_out = (stmf_ppioctl_data_t *)obuf;
13268fe96085Stim szeto if ((ppi_out == NULL) ||
13278fe96085Stim szeto (iocd->stmf_obuf_size < sizeof (stmf_ppioctl_data_t))) {
13288fe96085Stim szeto ret = EINVAL;
13298fe96085Stim szeto break;
13308fe96085Stim szeto }
13318fe96085Stim szeto ret = stmf_get_ppd_ioctl(ppi, ppi_out, &iocd->stmf_error);
1332fcf3ce44SJohn Forte break;
1333fcf3ce44SJohn Forte
1334fcf3ce44SJohn Forte case STMF_IOCTL_CLEAR_PP_DATA:
1335fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
1336fcf3ce44SJohn Forte ret = EACCES;
1337fcf3ce44SJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
1338fcf3ce44SJohn Forte break;
1339fcf3ce44SJohn Forte }
1340fcf3ce44SJohn Forte ppi = (stmf_ppioctl_data_t *)ibuf;
1341fcf3ce44SJohn Forte if ((ppi == NULL) ||
1342fcf3ce44SJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
1343fcf3ce44SJohn Forte ret = EINVAL;
1344fcf3ce44SJohn Forte break;
1345fcf3ce44SJohn Forte }
1346fcf3ce44SJohn Forte ret = stmf_delete_ppd_ioctl(ppi);
1347fcf3ce44SJohn Forte break;
1348fcf3ce44SJohn Forte
1349fcf3ce44SJohn Forte case STMF_IOCTL_CLEAR_TRACE:
1350fcf3ce44SJohn Forte stmf_trace_clear();
1351fcf3ce44SJohn Forte break;
1352fcf3ce44SJohn Forte
1353fcf3ce44SJohn Forte case STMF_IOCTL_ADD_TRACE:
1354fcf3ce44SJohn Forte if (iocd->stmf_ibuf_size && ibuf) {
1355fcf3ce44SJohn Forte ((uint8_t *)ibuf)[iocd->stmf_ibuf_size - 1] = 0;
1356fcf3ce44SJohn Forte stmf_trace("\nstradm", "%s\n", ibuf);
1357fcf3ce44SJohn Forte }
1358fcf3ce44SJohn Forte break;
1359fcf3ce44SJohn Forte
1360fcf3ce44SJohn Forte case STMF_IOCTL_GET_TRACE_POSITION:
1361fcf3ce44SJohn Forte if (obuf && (iocd->stmf_obuf_size > 3)) {
1362fcf3ce44SJohn Forte mutex_enter(&trace_buf_lock);
1363fcf3ce44SJohn Forte *((int *)obuf) = trace_buf_curndx;
1364fcf3ce44SJohn Forte mutex_exit(&trace_buf_lock);
1365fcf3ce44SJohn Forte } else {
1366fcf3ce44SJohn Forte ret = EINVAL;
1367fcf3ce44SJohn Forte }
1368fcf3ce44SJohn Forte break;
1369fcf3ce44SJohn Forte
1370fcf3ce44SJohn Forte case STMF_IOCTL_GET_TRACE:
1371fcf3ce44SJohn Forte if ((iocd->stmf_obuf_size == 0) || (iocd->stmf_ibuf_size < 4)) {
1372fcf3ce44SJohn Forte ret = EINVAL;
1373fcf3ce44SJohn Forte break;
1374fcf3ce44SJohn Forte }
1375fcf3ce44SJohn Forte i = *((int *)ibuf);
1376fcf3ce44SJohn Forte if ((i > trace_buf_size) || ((i + iocd->stmf_obuf_size) >
1377fcf3ce44SJohn Forte trace_buf_size)) {
1378fcf3ce44SJohn Forte ret = EINVAL;
1379fcf3ce44SJohn Forte break;
1380fcf3ce44SJohn Forte }
1381fcf3ce44SJohn Forte mutex_enter(&trace_buf_lock);
1382fcf3ce44SJohn Forte bcopy(stmf_trace_buf + i, obuf, iocd->stmf_obuf_size);
1383fcf3ce44SJohn Forte mutex_exit(&trace_buf_lock);
1384fcf3ce44SJohn Forte break;
1385fcf3ce44SJohn Forte
1386fcf3ce44SJohn Forte default:
1387fcf3ce44SJohn Forte ret = ENOTTY;
1388fcf3ce44SJohn Forte }
1389fcf3ce44SJohn Forte
1390fcf3ce44SJohn Forte if (ret == 0) {
1391fcf3ce44SJohn Forte ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
1392fcf3ce44SJohn Forte } else if (iocd->stmf_error) {
1393fcf3ce44SJohn Forte (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
1394fcf3ce44SJohn Forte }
1395fcf3ce44SJohn Forte if (obuf) {
1396fcf3ce44SJohn Forte kmem_free(obuf, iocd->stmf_obuf_size);
1397fcf3ce44SJohn Forte obuf = NULL;
1398fcf3ce44SJohn Forte }
1399fcf3ce44SJohn Forte if (ibuf) {
1400fcf3ce44SJohn Forte kmem_free(ibuf, iocd->stmf_ibuf_size);
1401fcf3ce44SJohn Forte ibuf = NULL;
1402fcf3ce44SJohn Forte }
1403fcf3ce44SJohn Forte kmem_free(iocd, sizeof (stmf_iocdata_t));
1404fcf3ce44SJohn Forte return (ret);
1405fcf3ce44SJohn Forte }
1406fcf3ce44SJohn Forte
1407fcf3ce44SJohn Forte static int
stmf_get_service_state()1408fcf3ce44SJohn Forte stmf_get_service_state()
1409fcf3ce44SJohn Forte {
1410fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
1411fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
1412fcf3ce44SJohn Forte int online = 0;
1413fcf3ce44SJohn Forte int offline = 0;
1414fcf3ce44SJohn Forte int onlining = 0;
1415fcf3ce44SJohn Forte int offlining = 0;
1416fcf3ce44SJohn Forte
1417fcf3ce44SJohn Forte ASSERT(mutex_owned(&stmf_state.stmf_lock));
1418fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1419fcf3ce44SJohn Forte ilport = ilport->ilport_next) {
1420fcf3ce44SJohn Forte if (ilport->ilport_state == STMF_STATE_OFFLINE)
1421fcf3ce44SJohn Forte offline++;
1422fcf3ce44SJohn Forte else if (ilport->ilport_state == STMF_STATE_ONLINE)
1423fcf3ce44SJohn Forte online++;
1424fcf3ce44SJohn Forte else if (ilport->ilport_state == STMF_STATE_ONLINING)
1425fcf3ce44SJohn Forte onlining++;
1426fcf3ce44SJohn Forte else if (ilport->ilport_state == STMF_STATE_OFFLINING)
1427fcf3ce44SJohn Forte offlining++;
1428fcf3ce44SJohn Forte }
1429fcf3ce44SJohn Forte
1430fcf3ce44SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
1431fcf3ce44SJohn Forte ilu = ilu->ilu_next) {
1432fcf3ce44SJohn Forte if (ilu->ilu_state == STMF_STATE_OFFLINE)
1433fcf3ce44SJohn Forte offline++;
1434fcf3ce44SJohn Forte else if (ilu->ilu_state == STMF_STATE_ONLINE)
1435fcf3ce44SJohn Forte online++;
1436fcf3ce44SJohn Forte else if (ilu->ilu_state == STMF_STATE_ONLINING)
1437fcf3ce44SJohn Forte onlining++;
1438fcf3ce44SJohn Forte else if (ilu->ilu_state == STMF_STATE_OFFLINING)
1439fcf3ce44SJohn Forte offlining++;
1440fcf3ce44SJohn Forte }
1441fcf3ce44SJohn Forte
1442fcf3ce44SJohn Forte if (stmf_state.stmf_service_running) {
1443fcf3ce44SJohn Forte if (onlining)
1444fcf3ce44SJohn Forte return (STMF_STATE_ONLINING);
1445fcf3ce44SJohn Forte else
1446fcf3ce44SJohn Forte return (STMF_STATE_ONLINE);
1447fcf3ce44SJohn Forte }
1448fcf3ce44SJohn Forte
1449fcf3ce44SJohn Forte if (offlining) {
1450fcf3ce44SJohn Forte return (STMF_STATE_OFFLINING);
1451fcf3ce44SJohn Forte }
1452fcf3ce44SJohn Forte
1453fcf3ce44SJohn Forte return (STMF_STATE_OFFLINE);
1454fcf3ce44SJohn Forte }
1455fcf3ce44SJohn Forte
1456fcf3ce44SJohn Forte static int
stmf_set_stmf_state(stmf_state_desc_t * std)1457fcf3ce44SJohn Forte stmf_set_stmf_state(stmf_state_desc_t *std)
1458fcf3ce44SJohn Forte {
1459fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
1460fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
1461fcf3ce44SJohn Forte stmf_state_change_info_t ssi;
1462fcf3ce44SJohn Forte int svc_state;
1463fcf3ce44SJohn Forte
1464fcf3ce44SJohn Forte ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
1465fcf3ce44SJohn Forte ssi.st_additional_info = NULL;
1466fcf3ce44SJohn Forte
1467fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1468fcf3ce44SJohn Forte if (!stmf_state.stmf_exclusive_open) {
1469fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1470fcf3ce44SJohn Forte return (EACCES);
1471fcf3ce44SJohn Forte }
1472fcf3ce44SJohn Forte
1473fcf3ce44SJohn Forte if (stmf_state.stmf_inventory_locked) {
1474fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1475fcf3ce44SJohn Forte return (EBUSY);
1476fcf3ce44SJohn Forte }
1477fcf3ce44SJohn Forte
1478fcf3ce44SJohn Forte if ((std->state != STMF_STATE_ONLINE) &&
1479fcf3ce44SJohn Forte (std->state != STMF_STATE_OFFLINE)) {
1480fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1481fcf3ce44SJohn Forte return (EINVAL);
1482fcf3ce44SJohn Forte }
1483fcf3ce44SJohn Forte
1484fcf3ce44SJohn Forte svc_state = stmf_get_service_state();
1485fcf3ce44SJohn Forte if ((svc_state == STMF_STATE_OFFLINING) ||
1486fcf3ce44SJohn Forte (svc_state == STMF_STATE_ONLINING)) {
1487fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1488fcf3ce44SJohn Forte return (EBUSY);
1489fcf3ce44SJohn Forte }
1490fcf3ce44SJohn Forte
1491fcf3ce44SJohn Forte if (svc_state == STMF_STATE_OFFLINE) {
1492fcf3ce44SJohn Forte if (std->config_state == STMF_CONFIG_INIT) {
1493fcf3ce44SJohn Forte if (std->state != STMF_STATE_OFFLINE) {
1494fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1495fcf3ce44SJohn Forte return (EINVAL);
1496fcf3ce44SJohn Forte }
1497fcf3ce44SJohn Forte stmf_state.stmf_config_state = STMF_CONFIG_INIT;
1498fcf3ce44SJohn Forte stmf_delete_all_ppds();
1499fcf3ce44SJohn Forte stmf_view_clear_config();
1500fcf3ce44SJohn Forte stmf_view_init();
1501fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1502fcf3ce44SJohn Forte return (0);
1503fcf3ce44SJohn Forte }
15045dfbf9beSSue Gleeson if ((stmf_state.stmf_config_state == STMF_CONFIG_INIT) ||
15055dfbf9beSSue Gleeson (stmf_state.stmf_config_state == STMF_CONFIG_NONE)) {
1506fcf3ce44SJohn Forte if (std->config_state != STMF_CONFIG_INIT_DONE) {
1507fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1508fcf3ce44SJohn Forte return (EINVAL);
1509fcf3ce44SJohn Forte }
1510fcf3ce44SJohn Forte stmf_state.stmf_config_state = STMF_CONFIG_INIT_DONE;
1511fcf3ce44SJohn Forte }
1512fcf3ce44SJohn Forte if (std->state == STMF_STATE_OFFLINE) {
1513fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1514fcf3ce44SJohn Forte return (0);
1515fcf3ce44SJohn Forte }
1516fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_INIT) {
1517fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1518fcf3ce44SJohn Forte return (EINVAL);
1519fcf3ce44SJohn Forte }
1520fcf3ce44SJohn Forte stmf_state.stmf_inventory_locked = 1;
1521fcf3ce44SJohn Forte stmf_state.stmf_service_running = 1;
1522fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1523fcf3ce44SJohn Forte
1524fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1525fcf3ce44SJohn Forte ilport = ilport->ilport_next) {
15264b31676fSsrivijitha dugganapalli if (stmf_state.stmf_default_lport_state !=
15274b31676fSsrivijitha dugganapalli STMF_STATE_ONLINE)
1528fcf3ce44SJohn Forte continue;
1529fcf3ce44SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_ONLINE,
1530fcf3ce44SJohn Forte ilport->ilport_lport, &ssi);
1531fcf3ce44SJohn Forte }
1532fcf3ce44SJohn Forte
1533fcf3ce44SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
1534fcf3ce44SJohn Forte ilu = ilu->ilu_next) {
15354b31676fSsrivijitha dugganapalli if (stmf_state.stmf_default_lu_state !=
15364b31676fSsrivijitha dugganapalli STMF_STATE_ONLINE)
1537fcf3ce44SJohn Forte continue;
1538fcf3ce44SJohn Forte (void) stmf_ctl(STMF_CMD_LU_ONLINE, ilu->ilu_lu, &ssi);
1539fcf3ce44SJohn Forte }
1540fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1541fcf3ce44SJohn Forte stmf_state.stmf_inventory_locked = 0;
1542fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1543fcf3ce44SJohn Forte return (0);
1544fcf3ce44SJohn Forte }
1545fcf3ce44SJohn Forte
1546fcf3ce44SJohn Forte /* svc_state is STMF_STATE_ONLINE here */
1547fcf3ce44SJohn Forte if ((std->state != STMF_STATE_OFFLINE) ||
1548fcf3ce44SJohn Forte (std->config_state == STMF_CONFIG_INIT)) {
1549fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1550fcf3ce44SJohn Forte return (EACCES);
1551fcf3ce44SJohn Forte }
1552fcf3ce44SJohn Forte
1553fcf3ce44SJohn Forte stmf_state.stmf_inventory_locked = 1;
1554fcf3ce44SJohn Forte stmf_state.stmf_service_running = 0;
1555640428aeSSue Gleeson
1556fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1557fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
1558fcf3ce44SJohn Forte ilport = ilport->ilport_next) {
1559fcf3ce44SJohn Forte if (ilport->ilport_state != STMF_STATE_ONLINE)
1560fcf3ce44SJohn Forte continue;
1561fcf3ce44SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE,
1562fcf3ce44SJohn Forte ilport->ilport_lport, &ssi);
1563fcf3ce44SJohn Forte }
1564fcf3ce44SJohn Forte
1565fcf3ce44SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
1566fcf3ce44SJohn Forte ilu = ilu->ilu_next) {
1567fcf3ce44SJohn Forte if (ilu->ilu_state != STMF_STATE_ONLINE)
1568fcf3ce44SJohn Forte continue;
1569fcf3ce44SJohn Forte (void) stmf_ctl(STMF_CMD_LU_OFFLINE, ilu->ilu_lu, &ssi);
1570fcf3ce44SJohn Forte }
1571fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1572fcf3ce44SJohn Forte stmf_state.stmf_inventory_locked = 0;
1573fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1574fcf3ce44SJohn Forte return (0);
1575fcf3ce44SJohn Forte }
1576fcf3ce44SJohn Forte
1577fcf3ce44SJohn Forte static int
stmf_get_stmf_state(stmf_state_desc_t * std)1578fcf3ce44SJohn Forte stmf_get_stmf_state(stmf_state_desc_t *std)
1579fcf3ce44SJohn Forte {
1580fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
1581fcf3ce44SJohn Forte std->state = stmf_get_service_state();
1582fcf3ce44SJohn Forte std->config_state = stmf_state.stmf_config_state;
1583fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
1584fcf3ce44SJohn Forte
1585fcf3ce44SJohn Forte return (0);
1586fcf3ce44SJohn Forte }
158709409df0SJeff Biseda
158845039663SJohn Forte /*
158945039663SJohn Forte * handles registration message from pppt for a logical unit
159045039663SJohn Forte */
159145039663SJohn Forte stmf_status_t
stmf_ic_lu_reg(stmf_ic_reg_dereg_lun_msg_t * msg,uint32_t type)159245039663SJohn Forte stmf_ic_lu_reg(stmf_ic_reg_dereg_lun_msg_t *msg, uint32_t type)
159345039663SJohn Forte {
159445039663SJohn Forte stmf_i_lu_provider_t *ilp;
159545039663SJohn Forte stmf_lu_provider_t *lp;
159645039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
159745039663SJohn Forte for (ilp = stmf_state.stmf_ilplist; ilp != NULL; ilp = ilp->ilp_next) {
159845039663SJohn Forte if (strcmp(msg->icrl_lu_provider_name,
159945039663SJohn Forte ilp->ilp_lp->lp_name) == 0) {
160045039663SJohn Forte lp = ilp->ilp_lp;
160145039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
160245039663SJohn Forte lp->lp_proxy_msg(msg->icrl_lun_id, msg->icrl_cb_arg,
160345039663SJohn Forte msg->icrl_cb_arg_len, type);
160445039663SJohn Forte return (STMF_SUCCESS);
160545039663SJohn Forte }
160645039663SJohn Forte }
160745039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
160845039663SJohn Forte return (STMF_SUCCESS);
160945039663SJohn Forte }
161045039663SJohn Forte
161145039663SJohn Forte /*
161245039663SJohn Forte * handles de-registration message from pppt for a logical unit
161345039663SJohn Forte */
161445039663SJohn Forte stmf_status_t
stmf_ic_lu_dereg(stmf_ic_reg_dereg_lun_msg_t * msg)161545039663SJohn Forte stmf_ic_lu_dereg(stmf_ic_reg_dereg_lun_msg_t *msg)
161645039663SJohn Forte {
161745039663SJohn Forte stmf_i_lu_provider_t *ilp;
161845039663SJohn Forte stmf_lu_provider_t *lp;
161945039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
162045039663SJohn Forte for (ilp = stmf_state.stmf_ilplist; ilp != NULL; ilp = ilp->ilp_next) {
162145039663SJohn Forte if (strcmp(msg->icrl_lu_provider_name,
162245039663SJohn Forte ilp->ilp_lp->lp_name) == 0) {
162345039663SJohn Forte lp = ilp->ilp_lp;
162445039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
162545039663SJohn Forte lp->lp_proxy_msg(msg->icrl_lun_id, NULL, 0,
162645039663SJohn Forte STMF_MSG_LU_DEREGISTER);
162745039663SJohn Forte return (STMF_SUCCESS);
162845039663SJohn Forte }
162945039663SJohn Forte }
163045039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
163145039663SJohn Forte return (STMF_SUCCESS);
163245039663SJohn Forte }
163345039663SJohn Forte
163445039663SJohn Forte /*
163545039663SJohn Forte * helper function to find a task that matches a task_msgid
163645039663SJohn Forte */
163745039663SJohn Forte scsi_task_t *
find_task_from_msgid(uint8_t * lu_id,stmf_ic_msgid_t task_msgid)163845039663SJohn Forte find_task_from_msgid(uint8_t *lu_id, stmf_ic_msgid_t task_msgid)
163945039663SJohn Forte {
164045039663SJohn Forte stmf_i_lu_t *ilu;
164145039663SJohn Forte stmf_i_scsi_task_t *itask;
164245039663SJohn Forte
164345039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
164445039663SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
164545039663SJohn Forte if (bcmp(lu_id, ilu->ilu_lu->lu_id->ident, 16) == 0) {
164645039663SJohn Forte break;
164745039663SJohn Forte }
164845039663SJohn Forte }
164945039663SJohn Forte
165045039663SJohn Forte if (ilu == NULL) {
165145039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
165245039663SJohn Forte return (NULL);
165345039663SJohn Forte }
165445039663SJohn Forte
165545039663SJohn Forte mutex_enter(&ilu->ilu_task_lock);
165645039663SJohn Forte for (itask = ilu->ilu_tasks; itask != NULL;
165745039663SJohn Forte itask = itask->itask_lu_next) {
165845039663SJohn Forte if (itask->itask_flags & (ITASK_IN_FREE_LIST |
165945039663SJohn Forte ITASK_BEING_ABORTED)) {
166045039663SJohn Forte continue;
166145039663SJohn Forte }
166245039663SJohn Forte if (itask->itask_proxy_msg_id == task_msgid) {
166345039663SJohn Forte break;
166445039663SJohn Forte }
166545039663SJohn Forte }
166645039663SJohn Forte mutex_exit(&ilu->ilu_task_lock);
166745039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
166845039663SJohn Forte
166945039663SJohn Forte if (itask != NULL) {
167045039663SJohn Forte return (itask->itask_task);
167145039663SJohn Forte } else {
167245039663SJohn Forte /* task not found. Likely already aborted. */
167345039663SJohn Forte return (NULL);
167445039663SJohn Forte }
167545039663SJohn Forte }
167645039663SJohn Forte
167745039663SJohn Forte /*
167845039663SJohn Forte * message received from pppt/ic
167945039663SJohn Forte */
168045039663SJohn Forte stmf_status_t
stmf_msg_rx(stmf_ic_msg_t * msg)168145039663SJohn Forte stmf_msg_rx(stmf_ic_msg_t *msg)
168245039663SJohn Forte {
168345039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
168445039663SJohn Forte if (stmf_state.stmf_alua_state != 1) {
168545039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
168645039663SJohn Forte cmn_err(CE_WARN, "stmf alua state is disabled");
168745039663SJohn Forte ic_msg_free(msg);
168845039663SJohn Forte return (STMF_FAILURE);
168945039663SJohn Forte }
169045039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
169145039663SJohn Forte
169245039663SJohn Forte switch (msg->icm_msg_type) {
169345039663SJohn Forte case STMF_ICM_REGISTER_LUN:
169445039663SJohn Forte (void) stmf_ic_lu_reg(
169545039663SJohn Forte (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg,
169645039663SJohn Forte STMF_MSG_LU_REGISTER);
169745039663SJohn Forte break;
169845039663SJohn Forte case STMF_ICM_LUN_ACTIVE:
169945039663SJohn Forte (void) stmf_ic_lu_reg(
170045039663SJohn Forte (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg,
170145039663SJohn Forte STMF_MSG_LU_ACTIVE);
170245039663SJohn Forte break;
170345039663SJohn Forte case STMF_ICM_DEREGISTER_LUN:
170445039663SJohn Forte (void) stmf_ic_lu_dereg(
170545039663SJohn Forte (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg);
170645039663SJohn Forte break;
170745039663SJohn Forte case STMF_ICM_SCSI_DATA:
170845039663SJohn Forte (void) stmf_ic_rx_scsi_data(
170945039663SJohn Forte (stmf_ic_scsi_data_msg_t *)msg->icm_msg);
171045039663SJohn Forte break;
171145039663SJohn Forte case STMF_ICM_SCSI_STATUS:
171245039663SJohn Forte (void) stmf_ic_rx_scsi_status(
171345039663SJohn Forte (stmf_ic_scsi_status_msg_t *)msg->icm_msg);
171445039663SJohn Forte break;
171545039663SJohn Forte case STMF_ICM_STATUS:
171645039663SJohn Forte (void) stmf_ic_rx_status(
171745039663SJohn Forte (stmf_ic_status_msg_t *)msg->icm_msg);
171845039663SJohn Forte break;
171945039663SJohn Forte default:
172045039663SJohn Forte cmn_err(CE_WARN, "unknown message received %d",
172145039663SJohn Forte msg->icm_msg_type);
172245039663SJohn Forte ic_msg_free(msg);
172345039663SJohn Forte return (STMF_FAILURE);
172445039663SJohn Forte }
172545039663SJohn Forte ic_msg_free(msg);
172645039663SJohn Forte return (STMF_SUCCESS);
172745039663SJohn Forte }
172845039663SJohn Forte
172945039663SJohn Forte stmf_status_t
stmf_ic_rx_status(stmf_ic_status_msg_t * msg)173045039663SJohn Forte stmf_ic_rx_status(stmf_ic_status_msg_t *msg)
173145039663SJohn Forte {
173245039663SJohn Forte stmf_i_local_port_t *ilport;
173345039663SJohn Forte
173445039663SJohn Forte if (msg->ics_msg_type != STMF_ICM_REGISTER_PROXY_PORT) {
173545039663SJohn Forte /* for now, ignore other message status */
173645039663SJohn Forte return (STMF_SUCCESS);
173745039663SJohn Forte }
173845039663SJohn Forte
173945039663SJohn Forte if (msg->ics_status != STMF_SUCCESS) {
174045039663SJohn Forte return (STMF_SUCCESS);
174145039663SJohn Forte }
174245039663SJohn Forte
174345039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
174445039663SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
174545039663SJohn Forte ilport = ilport->ilport_next) {
174645039663SJohn Forte if (msg->ics_msgid == ilport->ilport_reg_msgid) {
174745039663SJohn Forte ilport->ilport_proxy_registered = 1;
174845039663SJohn Forte break;
174945039663SJohn Forte }
175045039663SJohn Forte }
175145039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
175245039663SJohn Forte return (STMF_SUCCESS);
175345039663SJohn Forte }
175445039663SJohn Forte
175545039663SJohn Forte /*
175645039663SJohn Forte * handles scsi status message from pppt
175745039663SJohn Forte */
175845039663SJohn Forte stmf_status_t
stmf_ic_rx_scsi_status(stmf_ic_scsi_status_msg_t * msg)175945039663SJohn Forte stmf_ic_rx_scsi_status(stmf_ic_scsi_status_msg_t *msg)
176045039663SJohn Forte {
176145039663SJohn Forte scsi_task_t *task;
176245039663SJohn Forte
1763cbdc6dc7SJohn Forte /* is this a task management command */
1764cbdc6dc7SJohn Forte if (msg->icss_task_msgid & MSG_ID_TM_BIT) {
1765cbdc6dc7SJohn Forte return (STMF_SUCCESS);
1766cbdc6dc7SJohn Forte }
1767cbdc6dc7SJohn Forte
176845039663SJohn Forte task = find_task_from_msgid(msg->icss_lun_id, msg->icss_task_msgid);
176945039663SJohn Forte
177045039663SJohn Forte if (task == NULL) {
177145039663SJohn Forte return (STMF_SUCCESS);
177245039663SJohn Forte }
177345039663SJohn Forte
177445039663SJohn Forte task->task_scsi_status = msg->icss_status;
177545039663SJohn Forte task->task_sense_data = msg->icss_sense;
177645039663SJohn Forte task->task_sense_length = msg->icss_sense_len;
177745039663SJohn Forte (void) stmf_send_scsi_status(task, STMF_IOF_LU_DONE);
177845039663SJohn Forte
177945039663SJohn Forte return (STMF_SUCCESS);
178045039663SJohn Forte }
178145039663SJohn Forte
178245039663SJohn Forte /*
178345039663SJohn Forte * handles scsi data message from pppt
178445039663SJohn Forte */
178545039663SJohn Forte stmf_status_t
stmf_ic_rx_scsi_data(stmf_ic_scsi_data_msg_t * msg)178645039663SJohn Forte stmf_ic_rx_scsi_data(stmf_ic_scsi_data_msg_t *msg)
178745039663SJohn Forte {
178845039663SJohn Forte stmf_i_scsi_task_t *itask;
178945039663SJohn Forte scsi_task_t *task;
179045039663SJohn Forte stmf_xfer_data_t *xd = NULL;
179145039663SJohn Forte stmf_data_buf_t *dbuf;
179245039663SJohn Forte uint32_t sz, minsz, xd_sz, asz;
179345039663SJohn Forte
1794cbdc6dc7SJohn Forte /* is this a task management command */
1795cbdc6dc7SJohn Forte if (msg->icsd_task_msgid & MSG_ID_TM_BIT) {
1796cbdc6dc7SJohn Forte return (STMF_SUCCESS);
1797cbdc6dc7SJohn Forte }
1798cbdc6dc7SJohn Forte
179945039663SJohn Forte task = find_task_from_msgid(msg->icsd_lun_id, msg->icsd_task_msgid);
180045039663SJohn Forte if (task == NULL) {
180145039663SJohn Forte stmf_ic_msg_t *ic_xfer_done_msg = NULL;
180245039663SJohn Forte static uint64_t data_msg_id;
180345039663SJohn Forte stmf_status_t ic_ret = STMF_FAILURE;
180445039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
180545039663SJohn Forte data_msg_id = stmf_proxy_msg_id++;
180645039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
180745039663SJohn Forte /*
180845039663SJohn Forte * send xfer done status to pppt
180945039663SJohn Forte * for now, set the session id to 0 as we cannot
181045039663SJohn Forte * ascertain it since we cannot find the task
181145039663SJohn Forte */
181245039663SJohn Forte ic_xfer_done_msg = ic_scsi_data_xfer_done_msg_alloc(
181345039663SJohn Forte msg->icsd_task_msgid, 0, STMF_FAILURE, data_msg_id);
181445039663SJohn Forte if (ic_xfer_done_msg) {
181545039663SJohn Forte ic_ret = ic_tx_msg(ic_xfer_done_msg);
181645039663SJohn Forte if (ic_ret != STMF_IC_MSG_SUCCESS) {
181745039663SJohn Forte cmn_err(CE_WARN, "unable to xmit proxy msg");
181845039663SJohn Forte }
181945039663SJohn Forte }
182045039663SJohn Forte return (STMF_FAILURE);
182145039663SJohn Forte }
182245039663SJohn Forte
182345039663SJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
182445039663SJohn Forte dbuf = itask->itask_proxy_dbuf;
182545039663SJohn Forte
182691159e90SJohn Forte task->task_cmd_xfer_length += msg->icsd_data_len;
182745039663SJohn Forte
182845039663SJohn Forte if (task->task_additional_flags &
182945039663SJohn Forte TASK_AF_NO_EXPECTED_XFER_LENGTH) {
183045039663SJohn Forte task->task_expected_xfer_length =
183145039663SJohn Forte task->task_cmd_xfer_length;
183245039663SJohn Forte }
183345039663SJohn Forte
183445039663SJohn Forte sz = min(task->task_expected_xfer_length,
183545039663SJohn Forte task->task_cmd_xfer_length);
183645039663SJohn Forte
183745039663SJohn Forte xd_sz = msg->icsd_data_len;
183845039663SJohn Forte asz = xd_sz + sizeof (*xd) - 4;
183945039663SJohn Forte xd = (stmf_xfer_data_t *)kmem_zalloc(asz, KM_NOSLEEP);
184045039663SJohn Forte
184145039663SJohn Forte if (xd == NULL) {
184245039663SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
184345039663SJohn Forte STMF_ALLOC_FAILURE, NULL);
184445039663SJohn Forte return (STMF_FAILURE);
184545039663SJohn Forte }
184645039663SJohn Forte
184745039663SJohn Forte xd->alloc_size = asz;
184845039663SJohn Forte xd->size_left = xd_sz;
184945039663SJohn Forte bcopy(msg->icsd_data, xd->buf, xd_sz);
185045039663SJohn Forte
185145039663SJohn Forte sz = min(sz, xd->size_left);
185245039663SJohn Forte xd->size_left = sz;
185345039663SJohn Forte minsz = min(512, sz);
185445039663SJohn Forte
185545039663SJohn Forte if (dbuf == NULL)
185645039663SJohn Forte dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0);
185745039663SJohn Forte if (dbuf == NULL) {
185845039663SJohn Forte kmem_free(xd, xd->alloc_size);
185945039663SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
186045039663SJohn Forte STMF_ALLOC_FAILURE, NULL);
186145039663SJohn Forte return (STMF_FAILURE);
186245039663SJohn Forte }
186345039663SJohn Forte dbuf->db_lu_private = xd;
186491159e90SJohn Forte dbuf->db_relative_offset = task->task_nbytes_transferred;
186591159e90SJohn Forte stmf_xd_to_dbuf(dbuf, 0);
186645039663SJohn Forte
186745039663SJohn Forte dbuf->db_flags = DB_DIRECTION_TO_RPORT;
186845039663SJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
186945039663SJohn Forte return (STMF_SUCCESS);
187045039663SJohn Forte }
187145039663SJohn Forte
187245039663SJohn Forte stmf_status_t
stmf_proxy_scsi_cmd(scsi_task_t * task,stmf_data_buf_t * dbuf)187345039663SJohn Forte stmf_proxy_scsi_cmd(scsi_task_t *task, stmf_data_buf_t *dbuf)
187445039663SJohn Forte {
187545039663SJohn Forte stmf_i_scsi_task_t *itask =
187645039663SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
187745039663SJohn Forte stmf_i_local_port_t *ilport =
187845039663SJohn Forte (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
187945039663SJohn Forte stmf_ic_msg_t *ic_cmd_msg;
188045039663SJohn Forte stmf_ic_msg_status_t ic_ret;
188145039663SJohn Forte stmf_status_t ret = STMF_FAILURE;
188245039663SJohn Forte
1883437be372SJohn Forte if (stmf_state.stmf_alua_state != 1) {
1884437be372SJohn Forte cmn_err(CE_WARN, "stmf alua state is disabled");
188545039663SJohn Forte return (STMF_FAILURE);
188645039663SJohn Forte }
188745039663SJohn Forte
1888437be372SJohn Forte if (ilport->ilport_proxy_registered == 0) {
188945039663SJohn Forte return (STMF_FAILURE);
189045039663SJohn Forte }
189145039663SJohn Forte
189245039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
189345039663SJohn Forte itask->itask_proxy_msg_id = stmf_proxy_msg_id++;
189445039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
189545039663SJohn Forte itask->itask_proxy_dbuf = dbuf;
1896437be372SJohn Forte
1897437be372SJohn Forte /*
1898437be372SJohn Forte * stmf will now take over the task handling for this task
1899437be372SJohn Forte * but it still needs to be treated differently from other
1900cbdc6dc7SJohn Forte * default handled tasks, hence the ITASK_PROXY_TASK.
1901cbdc6dc7SJohn Forte * If this is a task management function, we're really just
1902cbdc6dc7SJohn Forte * duping the command to the peer. Set the TM bit so that
1903cbdc6dc7SJohn Forte * we can recognize this on return since we won't be completing
1904cbdc6dc7SJohn Forte * the proxied task in that case.
1905437be372SJohn Forte */
1906cbdc6dc7SJohn Forte if (task->task_mgmt_function) {
1907cbdc6dc7SJohn Forte itask->itask_proxy_msg_id |= MSG_ID_TM_BIT;
1908cbdc6dc7SJohn Forte } else {
1909fdff2149SJohn Forte uint32_t new, old;
1910fdff2149SJohn Forte do {
1911fdff2149SJohn Forte new = old = itask->itask_flags;
1912fdff2149SJohn Forte if (new & ITASK_BEING_ABORTED)
1913fdff2149SJohn Forte return (STMF_FAILURE);
1914fdff2149SJohn Forte new |= ITASK_DEFAULT_HANDLING | ITASK_PROXY_TASK;
1915fdff2149SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
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 }
192545039663SJohn Forte if (ic_cmd_msg) {
192645039663SJohn Forte ic_ret = ic_tx_msg(ic_cmd_msg);
192745039663SJohn Forte if (ic_ret == STMF_IC_MSG_SUCCESS) {
192845039663SJohn Forte ret = STMF_SUCCESS;
192945039663SJohn Forte }
193045039663SJohn Forte }
193145039663SJohn Forte return (ret);
193245039663SJohn Forte }
193345039663SJohn Forte
193445039663SJohn Forte
193545039663SJohn Forte stmf_status_t
pppt_modload()193645039663SJohn Forte pppt_modload()
193745039663SJohn Forte {
193845039663SJohn Forte int error;
193945039663SJohn Forte
194045039663SJohn Forte if (pppt_mod == NULL && ((pppt_mod =
194145039663SJohn Forte ddi_modopen("drv/pppt", KRTLD_MODE_FIRST, &error)) == NULL)) {
194245039663SJohn Forte cmn_err(CE_WARN, "Unable to load pppt");
194345039663SJohn Forte return (STMF_FAILURE);
194445039663SJohn Forte }
194545039663SJohn Forte
194645039663SJohn Forte if (ic_reg_port_msg_alloc == NULL && ((ic_reg_port_msg_alloc =
194745039663SJohn Forte (stmf_ic_reg_port_msg_alloc_func_t)
194845039663SJohn Forte ddi_modsym(pppt_mod, "stmf_ic_reg_port_msg_alloc",
194945039663SJohn Forte &error)) == NULL)) {
195045039663SJohn Forte cmn_err(CE_WARN,
195145039663SJohn Forte "Unable to find symbol - stmf_ic_reg_port_msg_alloc");
195245039663SJohn Forte return (STMF_FAILURE);
195345039663SJohn Forte }
195445039663SJohn Forte
195545039663SJohn Forte
195645039663SJohn Forte if (ic_dereg_port_msg_alloc == NULL && ((ic_dereg_port_msg_alloc =
195745039663SJohn Forte (stmf_ic_dereg_port_msg_alloc_func_t)
195845039663SJohn Forte ddi_modsym(pppt_mod, "stmf_ic_dereg_port_msg_alloc",
195945039663SJohn Forte &error)) == NULL)) {
196045039663SJohn Forte cmn_err(CE_WARN,
196145039663SJohn Forte "Unable to find symbol - stmf_ic_dereg_port_msg_alloc");
196245039663SJohn Forte return (STMF_FAILURE);
196345039663SJohn Forte }
196445039663SJohn Forte
196545039663SJohn Forte if (ic_reg_lun_msg_alloc == NULL && ((ic_reg_lun_msg_alloc =
196645039663SJohn Forte (stmf_ic_reg_lun_msg_alloc_func_t)
196745039663SJohn Forte ddi_modsym(pppt_mod, "stmf_ic_reg_lun_msg_alloc",
196845039663SJohn Forte &error)) == NULL)) {
196945039663SJohn Forte cmn_err(CE_WARN,
197045039663SJohn Forte "Unable to find symbol - stmf_ic_reg_lun_msg_alloc");
197145039663SJohn Forte return (STMF_FAILURE);
197245039663SJohn Forte }
197345039663SJohn Forte
197445039663SJohn Forte if (ic_lun_active_msg_alloc == NULL && ((ic_lun_active_msg_alloc =
197545039663SJohn Forte (stmf_ic_lun_active_msg_alloc_func_t)
197645039663SJohn Forte ddi_modsym(pppt_mod, "stmf_ic_lun_active_msg_alloc",
197745039663SJohn Forte &error)) == NULL)) {
197845039663SJohn Forte cmn_err(CE_WARN,
197945039663SJohn Forte "Unable to find symbol - stmf_ic_lun_active_msg_alloc");
198045039663SJohn Forte return (STMF_FAILURE);
198145039663SJohn Forte }
198245039663SJohn Forte
198345039663SJohn Forte if (ic_dereg_lun_msg_alloc == NULL && ((ic_dereg_lun_msg_alloc =
198445039663SJohn Forte (stmf_ic_dereg_lun_msg_alloc_func_t)
198545039663SJohn Forte ddi_modsym(pppt_mod, "stmf_ic_dereg_lun_msg_alloc",
198645039663SJohn Forte &error)) == NULL)) {
198745039663SJohn Forte cmn_err(CE_WARN,
198845039663SJohn Forte "Unable to find symbol - stmf_ic_dereg_lun_msg_alloc");
198945039663SJohn Forte return (STMF_FAILURE);
199045039663SJohn Forte }
199145039663SJohn Forte
199245039663SJohn Forte if (ic_scsi_cmd_msg_alloc == NULL && ((ic_scsi_cmd_msg_alloc =
199345039663SJohn Forte (stmf_ic_scsi_cmd_msg_alloc_func_t)
199445039663SJohn Forte ddi_modsym(pppt_mod, "stmf_ic_scsi_cmd_msg_alloc",
199545039663SJohn Forte &error)) == NULL)) {
199645039663SJohn Forte cmn_err(CE_WARN,
199745039663SJohn Forte "Unable to find symbol - stmf_ic_scsi_cmd_msg_alloc");
199845039663SJohn Forte return (STMF_FAILURE);
199945039663SJohn Forte }
200045039663SJohn Forte
200145039663SJohn Forte if (ic_scsi_data_xfer_done_msg_alloc == NULL &&
200245039663SJohn Forte ((ic_scsi_data_xfer_done_msg_alloc =
200345039663SJohn Forte (stmf_ic_scsi_data_xfer_done_msg_alloc_func_t)
200445039663SJohn Forte ddi_modsym(pppt_mod, "stmf_ic_scsi_data_xfer_done_msg_alloc",
200545039663SJohn Forte &error)) == NULL)) {
200645039663SJohn Forte cmn_err(CE_WARN,
200745039663SJohn Forte "Unable to find symbol -"
200845039663SJohn Forte "stmf_ic_scsi_data_xfer_done_msg_alloc");
200945039663SJohn Forte return (STMF_FAILURE);
201045039663SJohn Forte }
201145039663SJohn Forte
201245039663SJohn Forte if (ic_session_reg_msg_alloc == NULL &&
201345039663SJohn Forte ((ic_session_reg_msg_alloc =
201445039663SJohn Forte (stmf_ic_session_create_msg_alloc_func_t)
201545039663SJohn Forte ddi_modsym(pppt_mod, "stmf_ic_session_create_msg_alloc",
201645039663SJohn Forte &error)) == NULL)) {
201745039663SJohn Forte cmn_err(CE_WARN,
201845039663SJohn Forte "Unable to find symbol -"
201945039663SJohn Forte "stmf_ic_session_create_msg_alloc");
202045039663SJohn Forte return (STMF_FAILURE);
202145039663SJohn Forte }
202245039663SJohn Forte
202345039663SJohn Forte if (ic_session_dereg_msg_alloc == NULL &&
202445039663SJohn Forte ((ic_session_dereg_msg_alloc =
202545039663SJohn Forte (stmf_ic_session_destroy_msg_alloc_func_t)
202645039663SJohn Forte ddi_modsym(pppt_mod, "stmf_ic_session_destroy_msg_alloc",
202745039663SJohn Forte &error)) == NULL)) {
202845039663SJohn Forte cmn_err(CE_WARN,
202945039663SJohn Forte "Unable to find symbol -"
203045039663SJohn Forte "stmf_ic_session_destroy_msg_alloc");
203145039663SJohn Forte return (STMF_FAILURE);
203245039663SJohn Forte }
203345039663SJohn Forte
203445039663SJohn Forte if (ic_tx_msg == NULL && ((ic_tx_msg =
203545039663SJohn Forte (stmf_ic_tx_msg_func_t)ddi_modsym(pppt_mod, "stmf_ic_tx_msg",
203645039663SJohn Forte &error)) == NULL)) {
203745039663SJohn Forte cmn_err(CE_WARN, "Unable to find symbol - stmf_ic_tx_msg");
203845039663SJohn Forte return (STMF_FAILURE);
203945039663SJohn Forte }
204045039663SJohn Forte
204145039663SJohn Forte if (ic_msg_free == NULL && ((ic_msg_free =
204245039663SJohn Forte (stmf_ic_msg_free_func_t)ddi_modsym(pppt_mod, "stmf_ic_msg_free",
204345039663SJohn Forte &error)) == NULL)) {
204445039663SJohn Forte cmn_err(CE_WARN, "Unable to find symbol - stmf_ic_msg_free");
204545039663SJohn Forte return (STMF_FAILURE);
204645039663SJohn Forte }
204745039663SJohn Forte return (STMF_SUCCESS);
204845039663SJohn Forte }
204945039663SJohn Forte
205045039663SJohn Forte static void
stmf_get_alua_state(stmf_alua_state_desc_t * alua_state)205145039663SJohn Forte stmf_get_alua_state(stmf_alua_state_desc_t *alua_state)
205245039663SJohn Forte {
205345039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
205445039663SJohn Forte alua_state->alua_node = stmf_state.stmf_alua_node;
205545039663SJohn Forte alua_state->alua_state = stmf_state.stmf_alua_state;
205645039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
205745039663SJohn Forte }
205845039663SJohn Forte
205945039663SJohn Forte
206045039663SJohn Forte static int
stmf_set_alua_state(stmf_alua_state_desc_t * alua_state)206145039663SJohn Forte stmf_set_alua_state(stmf_alua_state_desc_t *alua_state)
206245039663SJohn Forte {
206345039663SJohn Forte stmf_i_local_port_t *ilport;
206445039663SJohn Forte stmf_i_lu_t *ilu;
206545039663SJohn Forte stmf_lu_t *lu;
206645039663SJohn Forte stmf_ic_msg_status_t ic_ret;
206745039663SJohn Forte stmf_ic_msg_t *ic_reg_lun, *ic_reg_port;
206845039663SJohn Forte stmf_local_port_t *lport;
206945039663SJohn Forte int ret = 0;
207045039663SJohn Forte
207145039663SJohn Forte if (alua_state->alua_state > 1 || alua_state->alua_node > 1) {
207245039663SJohn Forte return (EINVAL);
207345039663SJohn Forte }
207445039663SJohn Forte
207545039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
207645039663SJohn Forte if (alua_state->alua_state == 1) {
207745039663SJohn Forte if (pppt_modload() == STMF_FAILURE) {
207845039663SJohn Forte ret = EIO;
207945039663SJohn Forte goto err;
208045039663SJohn Forte }
208145039663SJohn Forte if (alua_state->alua_node != 0) {
208245039663SJohn Forte /* reset existing rtpids to new base */
208345039663SJohn Forte stmf_rtpid_counter = 255;
208445039663SJohn Forte }
208545039663SJohn Forte stmf_state.stmf_alua_node = alua_state->alua_node;
208645039663SJohn Forte stmf_state.stmf_alua_state = 1;
208745039663SJohn Forte /* register existing local ports with ppp */
208845039663SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
208945039663SJohn Forte ilport = ilport->ilport_next) {
2090cd36db67SJohn Forte /* skip standby ports and non-alua participants */
2091cd36db67SJohn Forte if (ilport->ilport_standby == 1 ||
2092cd36db67SJohn Forte ilport->ilport_alua == 0) {
209345039663SJohn Forte continue;
209445039663SJohn Forte }
209545039663SJohn Forte if (alua_state->alua_node != 0) {
209645039663SJohn Forte ilport->ilport_rtpid =
20971a5e258fSJosef 'Jeff' Sipek atomic_inc_16_nv(&stmf_rtpid_counter);
209845039663SJohn Forte }
209945039663SJohn Forte lport = ilport->ilport_lport;
210045039663SJohn Forte ic_reg_port = ic_reg_port_msg_alloc(
210145039663SJohn Forte lport->lport_id, ilport->ilport_rtpid,
210245039663SJohn Forte 0, NULL, stmf_proxy_msg_id);
210345039663SJohn Forte if (ic_reg_port) {
210445039663SJohn Forte ic_ret = ic_tx_msg(ic_reg_port);
210545039663SJohn Forte if (ic_ret == STMF_IC_MSG_SUCCESS) {
210645039663SJohn Forte ilport->ilport_reg_msgid =
210745039663SJohn Forte stmf_proxy_msg_id++;
210845039663SJohn Forte } else {
210945039663SJohn Forte cmn_err(CE_WARN,
211045039663SJohn Forte "error on port registration "
211145039663SJohn Forte "port - %s",
211245039663SJohn Forte ilport->ilport_kstat_tgt_name);
211345039663SJohn Forte }
211445039663SJohn Forte }
211545039663SJohn Forte }
211645039663SJohn Forte /* register existing logical units */
211745039663SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL;
211845039663SJohn Forte ilu = ilu->ilu_next) {
211945039663SJohn Forte if (ilu->ilu_access != STMF_LU_ACTIVE) {
212045039663SJohn Forte continue;
212145039663SJohn Forte }
212245039663SJohn Forte /* register with proxy module */
212345039663SJohn Forte lu = ilu->ilu_lu;
212445039663SJohn Forte if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
212545039663SJohn Forte lu->lu_lp->lp_alua_support) {
212645039663SJohn Forte ilu->ilu_alua = 1;
212745039663SJohn Forte /* allocate the register message */
212845039663SJohn Forte ic_reg_lun = ic_reg_lun_msg_alloc(
212945039663SJohn Forte lu->lu_id->ident, lu->lu_lp->lp_name,
213045039663SJohn Forte lu->lu_proxy_reg_arg_len,
213145039663SJohn Forte (uint8_t *)lu->lu_proxy_reg_arg,
213245039663SJohn Forte stmf_proxy_msg_id);
213345039663SJohn Forte /* send the message */
213445039663SJohn Forte if (ic_reg_lun) {
213545039663SJohn Forte ic_ret = ic_tx_msg(ic_reg_lun);
213645039663SJohn Forte if (ic_ret == STMF_IC_MSG_SUCCESS) {
213745039663SJohn Forte stmf_proxy_msg_id++;
213845039663SJohn Forte }
213945039663SJohn Forte }
214045039663SJohn Forte }
214145039663SJohn Forte }
214245039663SJohn Forte } else {
214345039663SJohn Forte stmf_state.stmf_alua_state = 0;
214445039663SJohn Forte }
214545039663SJohn Forte
214645039663SJohn Forte err:
214745039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
214845039663SJohn Forte return (ret);
214945039663SJohn Forte }
215045039663SJohn Forte
215145039663SJohn Forte
2152fcf3ce44SJohn Forte typedef struct {
2153fcf3ce44SJohn Forte void *bp; /* back pointer from internal struct to main struct */
2154fcf3ce44SJohn Forte int alloc_size;
2155fcf3ce44SJohn Forte } __istmf_t;
2156fcf3ce44SJohn Forte
2157fcf3ce44SJohn Forte typedef struct {
2158fcf3ce44SJohn Forte __istmf_t *fp; /* Framework private */
2159fcf3ce44SJohn Forte void *cp; /* Caller private */
2160fcf3ce44SJohn Forte void *ss; /* struct specific */
2161fcf3ce44SJohn Forte } __stmf_t;
2162fcf3ce44SJohn Forte
2163fcf3ce44SJohn Forte static struct {
2164fcf3ce44SJohn Forte int shared;
2165fcf3ce44SJohn Forte int fw_private;
2166fcf3ce44SJohn Forte } stmf_sizes[] = { { 0, 0 },
2167fcf3ce44SJohn Forte { GET_STRUCT_SIZE(stmf_lu_provider_t),
2168fcf3ce44SJohn Forte GET_STRUCT_SIZE(stmf_i_lu_provider_t) },
2169fcf3ce44SJohn Forte { GET_STRUCT_SIZE(stmf_port_provider_t),
2170fcf3ce44SJohn Forte GET_STRUCT_SIZE(stmf_i_port_provider_t) },
2171fcf3ce44SJohn Forte { GET_STRUCT_SIZE(stmf_local_port_t),
2172fcf3ce44SJohn Forte GET_STRUCT_SIZE(stmf_i_local_port_t) },
2173fcf3ce44SJohn Forte { GET_STRUCT_SIZE(stmf_lu_t),
2174fcf3ce44SJohn Forte GET_STRUCT_SIZE(stmf_i_lu_t) },
2175fcf3ce44SJohn Forte { GET_STRUCT_SIZE(stmf_scsi_session_t),
2176fcf3ce44SJohn Forte GET_STRUCT_SIZE(stmf_i_scsi_session_t) },
2177fcf3ce44SJohn Forte { GET_STRUCT_SIZE(scsi_task_t),
2178fcf3ce44SJohn Forte GET_STRUCT_SIZE(stmf_i_scsi_task_t) },
2179fcf3ce44SJohn Forte { GET_STRUCT_SIZE(stmf_data_buf_t),
2180fcf3ce44SJohn Forte GET_STRUCT_SIZE(__istmf_t) },
2181fcf3ce44SJohn Forte { GET_STRUCT_SIZE(stmf_dbuf_store_t),
2182fcf3ce44SJohn Forte GET_STRUCT_SIZE(__istmf_t) }
2183fcf3ce44SJohn Forte
2184fcf3ce44SJohn Forte };
2185fcf3ce44SJohn Forte
2186fcf3ce44SJohn Forte void *
stmf_alloc(stmf_struct_id_t struct_id,int additional_size,int flags)2187fcf3ce44SJohn Forte stmf_alloc(stmf_struct_id_t struct_id, int additional_size, int flags)
2188fcf3ce44SJohn Forte {
2189fcf3ce44SJohn Forte int stmf_size;
2190fcf3ce44SJohn Forte int kmem_flag;
2191fcf3ce44SJohn Forte __stmf_t *sh;
2192fcf3ce44SJohn Forte
2193fcf3ce44SJohn Forte if ((struct_id == 0) || (struct_id >= STMF_MAX_STRUCT_IDS))
2194fcf3ce44SJohn Forte return (NULL);
2195fcf3ce44SJohn Forte
2196fcf3ce44SJohn Forte if ((curthread->t_flag & T_INTR_THREAD) || (flags & AF_FORCE_NOSLEEP)) {
2197fcf3ce44SJohn Forte kmem_flag = KM_NOSLEEP;
2198fcf3ce44SJohn Forte } else {
2199fcf3ce44SJohn Forte kmem_flag = KM_SLEEP;
2200fcf3ce44SJohn Forte }
2201fcf3ce44SJohn Forte
2202fcf3ce44SJohn Forte additional_size = (additional_size + 7) & (~7);
2203fcf3ce44SJohn Forte stmf_size = stmf_sizes[struct_id].shared +
2204fcf3ce44SJohn Forte stmf_sizes[struct_id].fw_private + additional_size;
2205fcf3ce44SJohn Forte
22063fb517f7SJames Moore if (flags & AF_DONTZERO)
22073fb517f7SJames Moore sh = (__stmf_t *)kmem_alloc(stmf_size, kmem_flag);
22083fb517f7SJames Moore else
2209fcf3ce44SJohn Forte sh = (__stmf_t *)kmem_zalloc(stmf_size, kmem_flag);
2210fcf3ce44SJohn Forte
2211fcf3ce44SJohn Forte if (sh == NULL)
2212fcf3ce44SJohn Forte return (NULL);
2213fcf3ce44SJohn Forte
22142a8164dfSZhong Wang /*
22152a8164dfSZhong Wang * In principle, the implementation inside stmf_alloc should not
22162a8164dfSZhong Wang * be changed anyway. But the original order of framework private
22172a8164dfSZhong Wang * data and caller private data does not support sglist in the caller
22182a8164dfSZhong Wang * private data.
22192a8164dfSZhong Wang * To work around this, the memory segments of framework private
22202a8164dfSZhong Wang * data and caller private data are re-ordered here.
22212a8164dfSZhong Wang * A better solution is to provide a specific interface to allocate
22222a8164dfSZhong Wang * the sglist, then we will not need this workaround any more.
22232a8164dfSZhong Wang * But before the new interface is available, the memory segment
22242a8164dfSZhong Wang * ordering should be kept as is.
22252a8164dfSZhong Wang */
22262a8164dfSZhong Wang sh->cp = GET_BYTE_OFFSET(sh, stmf_sizes[struct_id].shared);
22272a8164dfSZhong Wang sh->fp = (__istmf_t *)GET_BYTE_OFFSET(sh,
22282a8164dfSZhong Wang stmf_sizes[struct_id].shared + additional_size);
2229fcf3ce44SJohn Forte
2230fcf3ce44SJohn Forte sh->fp->bp = sh;
2231fcf3ce44SJohn Forte /* Just store the total size instead of storing additional size */
2232fcf3ce44SJohn Forte sh->fp->alloc_size = stmf_size;
2233fcf3ce44SJohn Forte
2234fcf3ce44SJohn Forte return (sh);
2235fcf3ce44SJohn Forte }
2236fcf3ce44SJohn Forte
2237fcf3ce44SJohn Forte void
stmf_free(void * ptr)2238fcf3ce44SJohn Forte stmf_free(void *ptr)
2239fcf3ce44SJohn Forte {
2240fcf3ce44SJohn Forte __stmf_t *sh = (__stmf_t *)ptr;
2241fcf3ce44SJohn Forte
2242fcf3ce44SJohn Forte /*
2243fcf3ce44SJohn Forte * So far we dont need any struct specific processing. If such
2244fcf3ce44SJohn Forte * a need ever arises, then store the struct id in the framework
2245fcf3ce44SJohn Forte * private section and get it here as sh->fp->struct_id.
2246fcf3ce44SJohn Forte */
2247fcf3ce44SJohn Forte kmem_free(ptr, sh->fp->alloc_size);
2248fcf3ce44SJohn Forte }
2249fcf3ce44SJohn Forte
2250fcf3ce44SJohn Forte /*
2251fcf3ce44SJohn Forte * Given a pointer to stmf_lu_t, verifies if this lu is registered with the
2252fcf3ce44SJohn Forte * framework and returns a pointer to framework private data for the lu.
2253fcf3ce44SJohn Forte * Returns NULL if the lu was not found.
2254fcf3ce44SJohn Forte */
2255fcf3ce44SJohn Forte stmf_i_lu_t *
stmf_lookup_lu(stmf_lu_t * lu)2256fcf3ce44SJohn Forte stmf_lookup_lu(stmf_lu_t *lu)
2257fcf3ce44SJohn Forte {
2258fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
2259fcf3ce44SJohn Forte ASSERT(mutex_owned(&stmf_state.stmf_lock));
2260fcf3ce44SJohn Forte
2261fcf3ce44SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
2262fcf3ce44SJohn Forte if (ilu->ilu_lu == lu)
2263fcf3ce44SJohn Forte return (ilu);
2264fcf3ce44SJohn Forte }
2265fcf3ce44SJohn Forte return (NULL);
2266fcf3ce44SJohn Forte }
2267fcf3ce44SJohn Forte
2268fcf3ce44SJohn Forte /*
22691b7fc709Stim szeto * Given a pointer to stmf_local_port_t, verifies if this lport is registered
22701b7fc709Stim szeto * with the framework and returns a pointer to framework private data for
22711b7fc709Stim szeto * the lport.
22721b7fc709Stim szeto * Returns NULL if the lport was not found.
2273fcf3ce44SJohn Forte */
2274fcf3ce44SJohn Forte stmf_i_local_port_t *
stmf_lookup_lport(stmf_local_port_t * lport)2275fcf3ce44SJohn Forte stmf_lookup_lport(stmf_local_port_t *lport)
2276fcf3ce44SJohn Forte {
2277fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
2278fcf3ce44SJohn Forte ASSERT(mutex_owned(&stmf_state.stmf_lock));
2279fcf3ce44SJohn Forte
2280fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
2281fcf3ce44SJohn Forte ilport = ilport->ilport_next) {
2282fcf3ce44SJohn Forte if (ilport->ilport_lport == lport)
2283fcf3ce44SJohn Forte return (ilport);
2284fcf3ce44SJohn Forte }
2285fcf3ce44SJohn Forte return (NULL);
2286fcf3ce44SJohn Forte }
2287fcf3ce44SJohn Forte
2288fcf3ce44SJohn Forte stmf_status_t
stmf_register_lu_provider(stmf_lu_provider_t * lp)2289fcf3ce44SJohn Forte stmf_register_lu_provider(stmf_lu_provider_t *lp)
2290fcf3ce44SJohn Forte {
2291fcf3ce44SJohn Forte stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private;
2292fcf3ce44SJohn Forte stmf_pp_data_t *ppd;
2293fcf3ce44SJohn Forte uint32_t cb_flags;
2294fcf3ce44SJohn Forte
229545039663SJohn Forte if (lp->lp_lpif_rev != LPIF_REV_1 && lp->lp_lpif_rev != LPIF_REV_2)
2296fcf3ce44SJohn Forte return (STMF_FAILURE);
2297fcf3ce44SJohn Forte
2298fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2299fcf3ce44SJohn Forte ilp->ilp_next = stmf_state.stmf_ilplist;
2300fcf3ce44SJohn Forte stmf_state.stmf_ilplist = ilp;
2301fcf3ce44SJohn Forte stmf_state.stmf_nlps++;
2302fcf3ce44SJohn Forte
2303fcf3ce44SJohn Forte /* See if we need to do a callback */
2304fcf3ce44SJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2305fcf3ce44SJohn Forte if (strcmp(ppd->ppd_name, lp->lp_name) == 0) {
2306fcf3ce44SJohn Forte break;
2307fcf3ce44SJohn Forte }
2308fcf3ce44SJohn Forte }
2309fcf3ce44SJohn Forte if ((ppd == NULL) || (ppd->ppd_nv == NULL)) {
2310fcf3ce44SJohn Forte goto rlp_bail_out;
2311fcf3ce44SJohn Forte }
2312fcf3ce44SJohn Forte ilp->ilp_ppd = ppd;
2313fcf3ce44SJohn Forte ppd->ppd_provider = ilp;
2314fcf3ce44SJohn Forte if (lp->lp_cb == NULL)
2315fcf3ce44SJohn Forte goto rlp_bail_out;
2316fcf3ce44SJohn Forte ilp->ilp_cb_in_progress = 1;
2317fcf3ce44SJohn Forte cb_flags = STMF_PCB_PREG_COMPLETE;
2318fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
2319fcf3ce44SJohn Forte cb_flags |= STMF_PCB_STMF_ONLINING;
2320fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2321fcf3ce44SJohn Forte lp->lp_cb(lp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2322fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2323fcf3ce44SJohn Forte ilp->ilp_cb_in_progress = 0;
2324fcf3ce44SJohn Forte
2325fcf3ce44SJohn Forte rlp_bail_out:
2326fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2327fcf3ce44SJohn Forte
2328fcf3ce44SJohn Forte return (STMF_SUCCESS);
2329fcf3ce44SJohn Forte }
2330fcf3ce44SJohn Forte
2331fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_lu_provider(stmf_lu_provider_t * lp)2332fcf3ce44SJohn Forte stmf_deregister_lu_provider(stmf_lu_provider_t *lp)
2333fcf3ce44SJohn Forte {
2334fcf3ce44SJohn Forte stmf_i_lu_provider_t **ppilp;
2335fcf3ce44SJohn Forte stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private;
2336fcf3ce44SJohn Forte
2337fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2338fcf3ce44SJohn Forte if (ilp->ilp_nlus || ilp->ilp_cb_in_progress) {
2339fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2340fcf3ce44SJohn Forte return (STMF_BUSY);
2341fcf3ce44SJohn Forte }
2342fcf3ce44SJohn Forte for (ppilp = &stmf_state.stmf_ilplist; *ppilp != NULL;
2343fcf3ce44SJohn Forte ppilp = &((*ppilp)->ilp_next)) {
2344fcf3ce44SJohn Forte if (*ppilp == ilp) {
2345fcf3ce44SJohn Forte *ppilp = ilp->ilp_next;
2346fcf3ce44SJohn Forte stmf_state.stmf_nlps--;
2347fcf3ce44SJohn Forte if (ilp->ilp_ppd) {
2348fcf3ce44SJohn Forte ilp->ilp_ppd->ppd_provider = NULL;
2349fcf3ce44SJohn Forte ilp->ilp_ppd = NULL;
2350fcf3ce44SJohn Forte }
2351fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2352fcf3ce44SJohn Forte return (STMF_SUCCESS);
2353fcf3ce44SJohn Forte }
2354fcf3ce44SJohn Forte }
2355fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2356fcf3ce44SJohn Forte return (STMF_NOT_FOUND);
2357fcf3ce44SJohn Forte }
2358fcf3ce44SJohn Forte
2359fcf3ce44SJohn Forte stmf_status_t
stmf_register_port_provider(stmf_port_provider_t * pp)2360fcf3ce44SJohn Forte stmf_register_port_provider(stmf_port_provider_t *pp)
2361fcf3ce44SJohn Forte {
2362fcf3ce44SJohn Forte stmf_i_port_provider_t *ipp =
2363fcf3ce44SJohn Forte (stmf_i_port_provider_t *)pp->pp_stmf_private;
2364fcf3ce44SJohn Forte stmf_pp_data_t *ppd;
2365fcf3ce44SJohn Forte uint32_t cb_flags;
2366fcf3ce44SJohn Forte
2367fcf3ce44SJohn Forte if (pp->pp_portif_rev != PORTIF_REV_1)
2368fcf3ce44SJohn Forte return (STMF_FAILURE);
2369fcf3ce44SJohn Forte
2370fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2371fcf3ce44SJohn Forte ipp->ipp_next = stmf_state.stmf_ipplist;
2372fcf3ce44SJohn Forte stmf_state.stmf_ipplist = ipp;
2373fcf3ce44SJohn Forte stmf_state.stmf_npps++;
2374fcf3ce44SJohn Forte /* See if we need to do a callback */
2375fcf3ce44SJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2376fcf3ce44SJohn Forte if (strcmp(ppd->ppd_name, pp->pp_name) == 0) {
2377fcf3ce44SJohn Forte break;
2378fcf3ce44SJohn Forte }
2379fcf3ce44SJohn Forte }
2380fcf3ce44SJohn Forte if ((ppd == NULL) || (ppd->ppd_nv == NULL)) {
2381fcf3ce44SJohn Forte goto rpp_bail_out;
2382fcf3ce44SJohn Forte }
2383fcf3ce44SJohn Forte ipp->ipp_ppd = ppd;
2384fcf3ce44SJohn Forte ppd->ppd_provider = ipp;
2385fcf3ce44SJohn Forte if (pp->pp_cb == NULL)
2386fcf3ce44SJohn Forte goto rpp_bail_out;
2387fcf3ce44SJohn Forte ipp->ipp_cb_in_progress = 1;
2388fcf3ce44SJohn Forte cb_flags = STMF_PCB_PREG_COMPLETE;
2389fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
2390fcf3ce44SJohn Forte cb_flags |= STMF_PCB_STMF_ONLINING;
2391fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2392fcf3ce44SJohn Forte pp->pp_cb(pp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2393fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2394fcf3ce44SJohn Forte ipp->ipp_cb_in_progress = 0;
2395fcf3ce44SJohn Forte
2396fcf3ce44SJohn Forte rpp_bail_out:
2397fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2398fcf3ce44SJohn Forte
2399fcf3ce44SJohn Forte return (STMF_SUCCESS);
2400fcf3ce44SJohn Forte }
2401fcf3ce44SJohn Forte
2402fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_port_provider(stmf_port_provider_t * pp)2403fcf3ce44SJohn Forte stmf_deregister_port_provider(stmf_port_provider_t *pp)
2404fcf3ce44SJohn Forte {
2405fcf3ce44SJohn Forte stmf_i_port_provider_t *ipp =
2406fcf3ce44SJohn Forte (stmf_i_port_provider_t *)pp->pp_stmf_private;
2407fcf3ce44SJohn Forte stmf_i_port_provider_t **ppipp;
2408fcf3ce44SJohn Forte
2409fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2410fcf3ce44SJohn Forte if (ipp->ipp_npps || ipp->ipp_cb_in_progress) {
2411fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2412fcf3ce44SJohn Forte return (STMF_BUSY);
2413fcf3ce44SJohn Forte }
2414fcf3ce44SJohn Forte for (ppipp = &stmf_state.stmf_ipplist; *ppipp != NULL;
2415fcf3ce44SJohn Forte ppipp = &((*ppipp)->ipp_next)) {
2416fcf3ce44SJohn Forte if (*ppipp == ipp) {
2417fcf3ce44SJohn Forte *ppipp = ipp->ipp_next;
2418fcf3ce44SJohn Forte stmf_state.stmf_npps--;
2419fcf3ce44SJohn Forte if (ipp->ipp_ppd) {
2420fcf3ce44SJohn Forte ipp->ipp_ppd->ppd_provider = NULL;
2421fcf3ce44SJohn Forte ipp->ipp_ppd = NULL;
2422fcf3ce44SJohn Forte }
2423fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2424fcf3ce44SJohn Forte return (STMF_SUCCESS);
2425fcf3ce44SJohn Forte }
2426fcf3ce44SJohn Forte }
2427fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2428fcf3ce44SJohn Forte return (STMF_NOT_FOUND);
2429fcf3ce44SJohn Forte }
2430fcf3ce44SJohn Forte
2431fcf3ce44SJohn Forte int
stmf_load_ppd_ioctl(stmf_ppioctl_data_t * ppi,uint64_t * ppi_token,uint32_t * err_ret)24328fe96085Stim szeto stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
24338fe96085Stim szeto uint32_t *err_ret)
2434fcf3ce44SJohn Forte {
2435fcf3ce44SJohn Forte stmf_i_port_provider_t *ipp;
2436fcf3ce44SJohn Forte stmf_i_lu_provider_t *ilp;
2437fcf3ce44SJohn Forte stmf_pp_data_t *ppd;
2438fcf3ce44SJohn Forte nvlist_t *nv;
2439fcf3ce44SJohn Forte int s;
2440fcf3ce44SJohn Forte int ret;
2441fcf3ce44SJohn Forte
24428fe96085Stim szeto *err_ret = 0;
24438fe96085Stim szeto
2444fcf3ce44SJohn Forte if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
2445fcf3ce44SJohn Forte return (EINVAL);
2446fcf3ce44SJohn Forte }
2447fcf3ce44SJohn Forte
2448fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2449fcf3ce44SJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2450fcf3ce44SJohn Forte if (ppi->ppi_lu_provider) {
2451fcf3ce44SJohn Forte if (!ppd->ppd_lu_provider)
2452fcf3ce44SJohn Forte continue;
2453fcf3ce44SJohn Forte } else if (ppi->ppi_port_provider) {
2454fcf3ce44SJohn Forte if (!ppd->ppd_port_provider)
2455fcf3ce44SJohn Forte continue;
2456fcf3ce44SJohn Forte }
2457fcf3ce44SJohn Forte if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
2458fcf3ce44SJohn Forte break;
2459fcf3ce44SJohn Forte }
2460fcf3ce44SJohn Forte
2461fcf3ce44SJohn Forte if (ppd == NULL) {
2462fcf3ce44SJohn Forte /* New provider */
2463fcf3ce44SJohn Forte s = strlen(ppi->ppi_name);
2464fcf3ce44SJohn Forte if (s > 254) {
2465fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2466fcf3ce44SJohn Forte return (EINVAL);
2467fcf3ce44SJohn Forte }
2468fcf3ce44SJohn Forte s += sizeof (stmf_pp_data_t) - 7;
2469fcf3ce44SJohn Forte
2470fcf3ce44SJohn Forte ppd = kmem_zalloc(s, KM_NOSLEEP);
2471fcf3ce44SJohn Forte if (ppd == NULL) {
2472fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2473fcf3ce44SJohn Forte return (ENOMEM);
2474fcf3ce44SJohn Forte }
2475fcf3ce44SJohn Forte ppd->ppd_alloc_size = s;
2476fcf3ce44SJohn Forte (void) strcpy(ppd->ppd_name, ppi->ppi_name);
2477fcf3ce44SJohn Forte
2478fcf3ce44SJohn Forte /* See if this provider already exists */
2479fcf3ce44SJohn Forte if (ppi->ppi_lu_provider) {
2480fcf3ce44SJohn Forte ppd->ppd_lu_provider = 1;
2481fcf3ce44SJohn Forte for (ilp = stmf_state.stmf_ilplist; ilp != NULL;
2482fcf3ce44SJohn Forte ilp = ilp->ilp_next) {
2483fcf3ce44SJohn Forte if (strcmp(ppi->ppi_name,
2484fcf3ce44SJohn Forte ilp->ilp_lp->lp_name) == 0) {
2485fcf3ce44SJohn Forte ppd->ppd_provider = ilp;
2486fcf3ce44SJohn Forte ilp->ilp_ppd = ppd;
2487fcf3ce44SJohn Forte break;
2488fcf3ce44SJohn Forte }
2489fcf3ce44SJohn Forte }
2490fcf3ce44SJohn Forte } else {
2491fcf3ce44SJohn Forte ppd->ppd_port_provider = 1;
2492fcf3ce44SJohn Forte for (ipp = stmf_state.stmf_ipplist; ipp != NULL;
2493fcf3ce44SJohn Forte ipp = ipp->ipp_next) {
2494fcf3ce44SJohn Forte if (strcmp(ppi->ppi_name,
2495fcf3ce44SJohn Forte ipp->ipp_pp->pp_name) == 0) {
2496fcf3ce44SJohn Forte ppd->ppd_provider = ipp;
2497fcf3ce44SJohn Forte ipp->ipp_ppd = ppd;
2498fcf3ce44SJohn Forte break;
2499fcf3ce44SJohn Forte }
2500fcf3ce44SJohn Forte }
2501fcf3ce44SJohn Forte }
2502fcf3ce44SJohn Forte
2503fcf3ce44SJohn Forte /* Link this ppd in */
2504fcf3ce44SJohn Forte ppd->ppd_next = stmf_state.stmf_ppdlist;
2505fcf3ce44SJohn Forte stmf_state.stmf_ppdlist = ppd;
2506fcf3ce44SJohn Forte }
2507fcf3ce44SJohn Forte
25088fe96085Stim szeto /*
25098fe96085Stim szeto * User is requesting that the token be checked.
25108fe96085Stim szeto * If there was another set after the user's get
25118fe96085Stim szeto * it's an error
25128fe96085Stim szeto */
25138fe96085Stim szeto if (ppi->ppi_token_valid) {
25148fe96085Stim szeto if (ppi->ppi_token != ppd->ppd_token) {
25158fe96085Stim szeto *err_ret = STMF_IOCERR_PPD_UPDATED;
25168fe96085Stim szeto mutex_exit(&stmf_state.stmf_lock);
25178fe96085Stim szeto return (EINVAL);
25188fe96085Stim szeto }
25198fe96085Stim szeto }
25208fe96085Stim szeto
2521fcf3ce44SJohn Forte if ((ret = nvlist_unpack((char *)ppi->ppi_data,
2522fcf3ce44SJohn Forte (size_t)ppi->ppi_data_size, &nv, KM_NOSLEEP)) != 0) {
2523fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2524fcf3ce44SJohn Forte return (ret);
2525fcf3ce44SJohn Forte }
2526fcf3ce44SJohn Forte
2527fcf3ce44SJohn Forte /* Free any existing lists and add this one to the ppd */
2528fcf3ce44SJohn Forte nvlist_free(ppd->ppd_nv);
2529fcf3ce44SJohn Forte ppd->ppd_nv = nv;
2530fcf3ce44SJohn Forte
25318fe96085Stim szeto /* set the token for writes */
25328fe96085Stim szeto ppd->ppd_token++;
25338fe96085Stim szeto /* return token to caller */
25348fe96085Stim szeto if (ppi_token) {
25358fe96085Stim szeto *ppi_token = ppd->ppd_token;
25368fe96085Stim szeto }
25378fe96085Stim szeto
2538fcf3ce44SJohn Forte /* If there is a provider registered, do the notifications */
2539fcf3ce44SJohn Forte if (ppd->ppd_provider) {
2540fcf3ce44SJohn Forte uint32_t cb_flags = 0;
2541fcf3ce44SJohn Forte
2542fcf3ce44SJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
2543fcf3ce44SJohn Forte cb_flags |= STMF_PCB_STMF_ONLINING;
2544fcf3ce44SJohn Forte if (ppi->ppi_lu_provider) {
2545fcf3ce44SJohn Forte ilp = (stmf_i_lu_provider_t *)ppd->ppd_provider;
2546fcf3ce44SJohn Forte if (ilp->ilp_lp->lp_cb == NULL)
2547fcf3ce44SJohn Forte goto bail_out;
2548fcf3ce44SJohn Forte ilp->ilp_cb_in_progress = 1;
2549fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2550fcf3ce44SJohn Forte ilp->ilp_lp->lp_cb(ilp->ilp_lp,
2551fcf3ce44SJohn Forte STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2552fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2553fcf3ce44SJohn Forte ilp->ilp_cb_in_progress = 0;
2554fcf3ce44SJohn Forte } else {
2555fcf3ce44SJohn Forte ipp = (stmf_i_port_provider_t *)ppd->ppd_provider;
2556fcf3ce44SJohn Forte if (ipp->ipp_pp->pp_cb == NULL)
2557fcf3ce44SJohn Forte goto bail_out;
2558fcf3ce44SJohn Forte ipp->ipp_cb_in_progress = 1;
2559fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2560fcf3ce44SJohn Forte ipp->ipp_pp->pp_cb(ipp->ipp_pp,
2561fcf3ce44SJohn Forte STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
2562fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2563fcf3ce44SJohn Forte ipp->ipp_cb_in_progress = 0;
2564fcf3ce44SJohn Forte }
2565fcf3ce44SJohn Forte }
2566fcf3ce44SJohn Forte
2567fcf3ce44SJohn Forte bail_out:
2568fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2569fcf3ce44SJohn Forte
2570fcf3ce44SJohn Forte return (0);
2571fcf3ce44SJohn Forte }
2572fcf3ce44SJohn Forte
2573fcf3ce44SJohn Forte void
stmf_delete_ppd(stmf_pp_data_t * ppd)2574fcf3ce44SJohn Forte stmf_delete_ppd(stmf_pp_data_t *ppd)
2575fcf3ce44SJohn Forte {
2576fcf3ce44SJohn Forte stmf_pp_data_t **pppd;
2577fcf3ce44SJohn Forte
2578fcf3ce44SJohn Forte ASSERT(mutex_owned(&stmf_state.stmf_lock));
2579fcf3ce44SJohn Forte if (ppd->ppd_provider) {
2580fcf3ce44SJohn Forte if (ppd->ppd_lu_provider) {
2581fcf3ce44SJohn Forte ((stmf_i_lu_provider_t *)
2582fcf3ce44SJohn Forte ppd->ppd_provider)->ilp_ppd = NULL;
2583fcf3ce44SJohn Forte } else {
2584fcf3ce44SJohn Forte ((stmf_i_port_provider_t *)
2585fcf3ce44SJohn Forte ppd->ppd_provider)->ipp_ppd = NULL;
2586fcf3ce44SJohn Forte }
2587fcf3ce44SJohn Forte ppd->ppd_provider = NULL;
2588fcf3ce44SJohn Forte }
2589fcf3ce44SJohn Forte
2590fcf3ce44SJohn Forte for (pppd = &stmf_state.stmf_ppdlist; *pppd != NULL;
2591fcf3ce44SJohn Forte pppd = &((*pppd)->ppd_next)) {
2592fcf3ce44SJohn Forte if (*pppd == ppd)
2593fcf3ce44SJohn Forte break;
2594fcf3ce44SJohn Forte }
2595fcf3ce44SJohn Forte
2596fcf3ce44SJohn Forte if (*pppd == NULL)
2597fcf3ce44SJohn Forte return;
2598fcf3ce44SJohn Forte
2599fcf3ce44SJohn Forte *pppd = ppd->ppd_next;
2600fcf3ce44SJohn Forte nvlist_free(ppd->ppd_nv);
2601fcf3ce44SJohn Forte
2602fcf3ce44SJohn Forte kmem_free(ppd, ppd->ppd_alloc_size);
2603fcf3ce44SJohn Forte }
2604fcf3ce44SJohn Forte
2605fcf3ce44SJohn Forte int
stmf_delete_ppd_ioctl(stmf_ppioctl_data_t * ppi)2606fcf3ce44SJohn Forte stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi)
2607fcf3ce44SJohn Forte {
2608fcf3ce44SJohn Forte stmf_pp_data_t *ppd;
2609fcf3ce44SJohn Forte int ret = ENOENT;
2610fcf3ce44SJohn Forte
2611fcf3ce44SJohn Forte if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
2612fcf3ce44SJohn Forte return (EINVAL);
2613fcf3ce44SJohn Forte }
2614fcf3ce44SJohn Forte
2615fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
2616fcf3ce44SJohn Forte
2617fcf3ce44SJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
2618fcf3ce44SJohn Forte if (ppi->ppi_lu_provider) {
2619fcf3ce44SJohn Forte if (!ppd->ppd_lu_provider)
2620fcf3ce44SJohn Forte continue;
2621fcf3ce44SJohn Forte } else if (ppi->ppi_port_provider) {
2622fcf3ce44SJohn Forte if (!ppd->ppd_port_provider)
2623fcf3ce44SJohn Forte continue;
2624fcf3ce44SJohn Forte }
2625fcf3ce44SJohn Forte if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
2626fcf3ce44SJohn Forte break;
2627fcf3ce44SJohn Forte }
2628fcf3ce44SJohn Forte
2629fcf3ce44SJohn Forte if (ppd) {
2630fcf3ce44SJohn Forte ret = 0;
2631fcf3ce44SJohn Forte stmf_delete_ppd(ppd);
2632fcf3ce44SJohn Forte }
2633fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
2634fcf3ce44SJohn Forte
2635fcf3ce44SJohn Forte return (ret);
2636fcf3ce44SJohn Forte }
2637fcf3ce44SJohn Forte
26388fe96085Stim szeto int
stmf_get_ppd_ioctl(stmf_ppioctl_data_t * ppi,stmf_ppioctl_data_t * ppi_out,uint32_t * err_ret)26398fe96085Stim szeto stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
26408fe96085Stim szeto uint32_t *err_ret)
26418fe96085Stim szeto {
26428fe96085Stim szeto stmf_pp_data_t *ppd;
26438fe96085Stim szeto size_t req_size;
26448fe96085Stim szeto int ret = ENOENT;
26458fe96085Stim szeto char *bufp = (char *)ppi_out->ppi_data;
26468fe96085Stim szeto
26478fe96085Stim szeto if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
26488fe96085Stim szeto return (EINVAL);
26498fe96085Stim szeto }
26508fe96085Stim szeto
26518fe96085Stim szeto mutex_enter(&stmf_state.stmf_lock);
26528fe96085Stim szeto
26538fe96085Stim szeto for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
26548fe96085Stim szeto if (ppi->ppi_lu_provider) {
26558fe96085Stim szeto if (!ppd->ppd_lu_provider)
26568fe96085Stim szeto continue;
26578fe96085Stim szeto } else if (ppi->ppi_port_provider) {
26588fe96085Stim szeto if (!ppd->ppd_port_provider)
26598fe96085Stim szeto continue;
26608fe96085Stim szeto }
26618fe96085Stim szeto if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
26628fe96085Stim szeto break;
26638fe96085Stim szeto }
26648fe96085Stim szeto
26658fe96085Stim szeto if (ppd && ppd->ppd_nv) {
26668fe96085Stim szeto ppi_out->ppi_token = ppd->ppd_token;
26678fe96085Stim szeto if ((ret = nvlist_size(ppd->ppd_nv, &req_size,
26688fe96085Stim szeto NV_ENCODE_XDR)) != 0) {
26698fe96085Stim szeto goto done;
26708fe96085Stim szeto }
26718fe96085Stim szeto ppi_out->ppi_data_size = req_size;
26728fe96085Stim szeto if (req_size > ppi->ppi_data_size) {
26738fe96085Stim szeto *err_ret = STMF_IOCERR_INSUFFICIENT_BUF;
26748fe96085Stim szeto ret = EINVAL;
26758fe96085Stim szeto goto done;
26768fe96085Stim szeto }
26778fe96085Stim szeto
26788fe96085Stim szeto if ((ret = nvlist_pack(ppd->ppd_nv, &bufp, &req_size,
26798fe96085Stim szeto NV_ENCODE_XDR, 0)) != 0) {
26808fe96085Stim szeto goto done;
26818fe96085Stim szeto }
26828fe96085Stim szeto ret = 0;
26838fe96085Stim szeto }
26848fe96085Stim szeto
26858fe96085Stim szeto done:
26868fe96085Stim szeto mutex_exit(&stmf_state.stmf_lock);
26878fe96085Stim szeto
26888fe96085Stim szeto return (ret);
26898fe96085Stim szeto }
26908fe96085Stim szeto
2691fcf3ce44SJohn Forte void
stmf_delete_all_ppds()2692fcf3ce44SJohn Forte stmf_delete_all_ppds()
2693fcf3ce44SJohn Forte {
2694fcf3ce44SJohn Forte stmf_pp_data_t *ppd, *nppd;
2695fcf3ce44SJohn Forte
2696fcf3ce44SJohn Forte ASSERT(mutex_owned(&stmf_state.stmf_lock));
2697fcf3ce44SJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = nppd) {
2698fcf3ce44SJohn Forte nppd = ppd->ppd_next;
2699fcf3ce44SJohn Forte stmf_delete_ppd(ppd);
2700fcf3ce44SJohn Forte }
2701fcf3ce44SJohn Forte }
2702fcf3ce44SJohn Forte
2703034d83c4Stim szeto /*
2704034d83c4Stim szeto * 16 is the max string length of a protocol_ident, increase
2705034d83c4Stim szeto * the size if needed.
2706034d83c4Stim szeto */
2707034d83c4Stim szeto #define STMF_KSTAT_LU_SZ (STMF_GUID_INPUT + 1 + 256)
2708034d83c4Stim szeto #define STMF_KSTAT_TGT_SZ (256 * 2 + 16)
2709034d83c4Stim szeto
2710034d83c4Stim szeto /*
2711034d83c4Stim szeto * This array matches the Protocol Identifier in stmf_ioctl.h
2712034d83c4Stim szeto */
2713427fcaf8Stim szeto #define MAX_PROTO_STR_LEN 32
2714427fcaf8Stim szeto
2715034d83c4Stim szeto char *protocol_ident[PROTOCOL_ANY] = {
2716034d83c4Stim szeto "Fibre Channel",
2717034d83c4Stim szeto "Parallel SCSI",
2718034d83c4Stim szeto "SSA",
2719034d83c4Stim szeto "IEEE_1394",
2720034d83c4Stim szeto "SRP",
2721034d83c4Stim szeto "iSCSI",
2722034d83c4Stim szeto "SAS",
2723034d83c4Stim szeto "ADT",
2724034d83c4Stim szeto "ATAPI",
2725034d83c4Stim szeto "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"
2726034d83c4Stim szeto };
2727034d83c4Stim szeto
2728034d83c4Stim szeto /*
2729034d83c4Stim szeto * Update the lun wait/run queue count
2730034d83c4Stim szeto */
2731034d83c4Stim szeto static void
stmf_update_kstat_lu_q(scsi_task_t * task,void func ())2732034d83c4Stim szeto stmf_update_kstat_lu_q(scsi_task_t *task, void func())
2733034d83c4Stim szeto {
2734034d83c4Stim szeto stmf_i_lu_t *ilu;
2735034d83c4Stim szeto kstat_io_t *kip;
2736034d83c4Stim szeto
2737034d83c4Stim szeto if (task->task_lu == dlun0)
2738034d83c4Stim szeto return;
2739034d83c4Stim szeto ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
2740034d83c4Stim szeto if (ilu != NULL && ilu->ilu_kstat_io != NULL) {
2741034d83c4Stim szeto kip = KSTAT_IO_PTR(ilu->ilu_kstat_io);
2742034d83c4Stim szeto if (kip != NULL) {
2743034d83c4Stim szeto func(kip);
2744034d83c4Stim szeto }
2745034d83c4Stim szeto }
2746034d83c4Stim szeto }
2747034d83c4Stim szeto
2748034d83c4Stim szeto /*
2749034d83c4Stim szeto * Update the target(lport) wait/run queue count
2750034d83c4Stim szeto */
2751034d83c4Stim szeto static void
stmf_update_kstat_lport_q(scsi_task_t * task,void func ())2752034d83c4Stim szeto stmf_update_kstat_lport_q(scsi_task_t *task, void func())
2753034d83c4Stim szeto {
2754034d83c4Stim szeto stmf_i_local_port_t *ilp;
2755034d83c4Stim szeto kstat_io_t *kip;
2756034d83c4Stim szeto
2757034d83c4Stim szeto ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
2758034d83c4Stim szeto if (ilp != NULL && ilp->ilport_kstat_io != NULL) {
2759034d83c4Stim szeto kip = KSTAT_IO_PTR(ilp->ilport_kstat_io);
2760034d83c4Stim szeto if (kip != NULL) {
2761034d83c4Stim szeto mutex_enter(ilp->ilport_kstat_io->ks_lock);
2762034d83c4Stim szeto func(kip);
2763034d83c4Stim szeto mutex_exit(ilp->ilport_kstat_io->ks_lock);
2764034d83c4Stim szeto }
2765034d83c4Stim szeto }
2766034d83c4Stim szeto }
2767034d83c4Stim szeto
2768034d83c4Stim szeto static void
stmf_update_kstat_lport_io(scsi_task_t * task,stmf_data_buf_t * dbuf)2769034d83c4Stim szeto stmf_update_kstat_lport_io(scsi_task_t *task, stmf_data_buf_t *dbuf)
2770034d83c4Stim szeto {
2771034d83c4Stim szeto stmf_i_local_port_t *ilp;
2772034d83c4Stim szeto kstat_io_t *kip;
2773034d83c4Stim szeto
2774034d83c4Stim szeto ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
2775034d83c4Stim szeto if (ilp != NULL && ilp->ilport_kstat_io != NULL) {
2776034d83c4Stim szeto kip = KSTAT_IO_PTR(ilp->ilport_kstat_io);
2777034d83c4Stim szeto if (kip != NULL) {
2778034d83c4Stim szeto mutex_enter(ilp->ilport_kstat_io->ks_lock);
2779034d83c4Stim szeto STMF_UPDATE_KSTAT_IO(kip, dbuf);
2780034d83c4Stim szeto mutex_exit(ilp->ilport_kstat_io->ks_lock);
2781034d83c4Stim szeto }
2782034d83c4Stim szeto }
2783034d83c4Stim szeto }
2784034d83c4Stim szeto
2785034d83c4Stim szeto static void
stmf_update_kstat_lu_io(scsi_task_t * task,stmf_data_buf_t * dbuf)2786034d83c4Stim szeto stmf_update_kstat_lu_io(scsi_task_t *task, stmf_data_buf_t *dbuf)
2787034d83c4Stim szeto {
2788034d83c4Stim szeto stmf_i_lu_t *ilu;
2789034d83c4Stim szeto kstat_io_t *kip;
2790034d83c4Stim szeto
2791034d83c4Stim szeto ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
2792034d83c4Stim szeto if (ilu != NULL && ilu->ilu_kstat_io != NULL) {
2793034d83c4Stim szeto kip = KSTAT_IO_PTR(ilu->ilu_kstat_io);
2794034d83c4Stim szeto if (kip != NULL) {
2795034d83c4Stim szeto mutex_enter(ilu->ilu_kstat_io->ks_lock);
2796034d83c4Stim szeto STMF_UPDATE_KSTAT_IO(kip, dbuf);
2797034d83c4Stim szeto mutex_exit(ilu->ilu_kstat_io->ks_lock);
2798034d83c4Stim szeto }
2799034d83c4Stim szeto }
2800034d83c4Stim szeto }
2801034d83c4Stim szeto
2802034d83c4Stim szeto static void
stmf_create_kstat_lu(stmf_i_lu_t * ilu)2803034d83c4Stim szeto stmf_create_kstat_lu(stmf_i_lu_t *ilu)
2804034d83c4Stim szeto {
2805034d83c4Stim szeto char ks_nm[KSTAT_STRLEN];
2806034d83c4Stim szeto stmf_kstat_lu_info_t *ks_lu;
2807034d83c4Stim szeto
2808034d83c4Stim szeto /* create kstat lun info */
2809034d83c4Stim szeto ks_lu = (stmf_kstat_lu_info_t *)kmem_zalloc(STMF_KSTAT_LU_SZ,
2810034d83c4Stim szeto KM_NOSLEEP);
2811034d83c4Stim szeto if (ks_lu == NULL) {
2812034d83c4Stim szeto cmn_err(CE_WARN, "STMF: kmem_zalloc failed");
2813034d83c4Stim szeto return;
2814034d83c4Stim szeto }
2815034d83c4Stim szeto
2816034d83c4Stim szeto bzero(ks_nm, sizeof (ks_nm));
2817034d83c4Stim szeto (void) sprintf(ks_nm, "stmf_lu_%"PRIxPTR"", (uintptr_t)ilu);
2818034d83c4Stim szeto if ((ilu->ilu_kstat_info = kstat_create(STMF_MODULE_NAME, 0,
2819034d83c4Stim szeto ks_nm, "misc", KSTAT_TYPE_NAMED,
2820034d83c4Stim szeto sizeof (stmf_kstat_lu_info_t) / sizeof (kstat_named_t),
2821034d83c4Stim szeto KSTAT_FLAG_VIRTUAL)) == NULL) {
2822034d83c4Stim szeto kmem_free(ks_lu, STMF_KSTAT_LU_SZ);
2823034d83c4Stim szeto cmn_err(CE_WARN, "STMF: kstat_create lu failed");
2824034d83c4Stim szeto return;
2825034d83c4Stim szeto }
2826034d83c4Stim szeto
2827034d83c4Stim szeto ilu->ilu_kstat_info->ks_data_size = STMF_KSTAT_LU_SZ;
2828034d83c4Stim szeto ilu->ilu_kstat_info->ks_data = ks_lu;
2829034d83c4Stim szeto
2830034d83c4Stim szeto kstat_named_init(&ks_lu->i_lun_guid, "lun-guid",
2831034d83c4Stim szeto KSTAT_DATA_STRING);
2832034d83c4Stim szeto kstat_named_init(&ks_lu->i_lun_alias, "lun-alias",
2833034d83c4Stim szeto KSTAT_DATA_STRING);
2834034d83c4Stim szeto
2835034d83c4Stim szeto /* convert guid to hex string */
2836034d83c4Stim szeto int i;
2837034d83c4Stim szeto uint8_t *p = ilu->ilu_lu->lu_id->ident;
2838034d83c4Stim szeto bzero(ilu->ilu_ascii_hex_guid, sizeof (ilu->ilu_ascii_hex_guid));
2839034d83c4Stim szeto for (i = 0; i < STMF_GUID_INPUT / 2; i++) {
2840034d83c4Stim szeto (void) sprintf(&ilu->ilu_ascii_hex_guid[i * 2], "%02x", p[i]);
2841034d83c4Stim szeto }
2842034d83c4Stim szeto kstat_named_setstr(&ks_lu->i_lun_guid,
2843034d83c4Stim szeto (const char *)ilu->ilu_ascii_hex_guid);
2844034d83c4Stim szeto kstat_named_setstr(&ks_lu->i_lun_alias,
2845034d83c4Stim szeto (const char *)ilu->ilu_lu->lu_alias);
2846034d83c4Stim szeto kstat_install(ilu->ilu_kstat_info);
2847034d83c4Stim szeto
2848034d83c4Stim szeto /* create kstat lun io */
2849034d83c4Stim szeto bzero(ks_nm, sizeof (ks_nm));
2850034d83c4Stim szeto (void) sprintf(ks_nm, "stmf_lu_io_%"PRIxPTR"", (uintptr_t)ilu);
2851034d83c4Stim szeto if ((ilu->ilu_kstat_io = kstat_create(STMF_MODULE_NAME, 0,
2852034d83c4Stim szeto ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
2853034d83c4Stim szeto cmn_err(CE_WARN, "STMF: kstat_create lu_io failed");
2854034d83c4Stim szeto return;
2855034d83c4Stim szeto }
2856034d83c4Stim szeto mutex_init(&ilu->ilu_kstat_lock, NULL, MUTEX_DRIVER, 0);
2857034d83c4Stim szeto ilu->ilu_kstat_io->ks_lock = &ilu->ilu_kstat_lock;
2858034d83c4Stim szeto kstat_install(ilu->ilu_kstat_io);
2859034d83c4Stim szeto }
2860034d83c4Stim szeto
2861034d83c4Stim szeto static void
stmf_create_kstat_lport(stmf_i_local_port_t * ilport)2862034d83c4Stim szeto stmf_create_kstat_lport(stmf_i_local_port_t *ilport)
2863034d83c4Stim szeto {
2864034d83c4Stim szeto char ks_nm[KSTAT_STRLEN];
2865034d83c4Stim szeto stmf_kstat_tgt_info_t *ks_tgt;
2866034d83c4Stim szeto int id, len;
2867034d83c4Stim szeto
2868034d83c4Stim szeto /* create kstat lport info */
2869034d83c4Stim szeto ks_tgt = (stmf_kstat_tgt_info_t *)kmem_zalloc(STMF_KSTAT_TGT_SZ,
2870034d83c4Stim szeto KM_NOSLEEP);
2871034d83c4Stim szeto if (ks_tgt == NULL) {
2872034d83c4Stim szeto cmn_err(CE_WARN, "STMF: kmem_zalloc failed");
2873034d83c4Stim szeto return;
2874034d83c4Stim szeto }
2875034d83c4Stim szeto
2876034d83c4Stim szeto bzero(ks_nm, sizeof (ks_nm));
2877034d83c4Stim szeto (void) sprintf(ks_nm, "stmf_tgt_%"PRIxPTR"", (uintptr_t)ilport);
2878034d83c4Stim szeto if ((ilport->ilport_kstat_info = kstat_create(STMF_MODULE_NAME,
2879034d83c4Stim szeto 0, ks_nm, "misc", KSTAT_TYPE_NAMED,
2880034d83c4Stim szeto sizeof (stmf_kstat_tgt_info_t) / sizeof (kstat_named_t),
2881034d83c4Stim szeto KSTAT_FLAG_VIRTUAL)) == NULL) {
2882034d83c4Stim szeto kmem_free(ks_tgt, STMF_KSTAT_TGT_SZ);
2883034d83c4Stim szeto cmn_err(CE_WARN, "STMF: kstat_create target failed");
2884034d83c4Stim szeto return;
2885034d83c4Stim szeto }
2886034d83c4Stim szeto
2887034d83c4Stim szeto ilport->ilport_kstat_info->ks_data_size = STMF_KSTAT_TGT_SZ;
2888034d83c4Stim szeto ilport->ilport_kstat_info->ks_data = ks_tgt;
2889034d83c4Stim szeto
2890034d83c4Stim szeto kstat_named_init(&ks_tgt->i_tgt_name, "target-name",
2891034d83c4Stim szeto KSTAT_DATA_STRING);
2892034d83c4Stim szeto kstat_named_init(&ks_tgt->i_tgt_alias, "target-alias",
2893034d83c4Stim szeto KSTAT_DATA_STRING);
2894034d83c4Stim szeto kstat_named_init(&ks_tgt->i_protocol, "protocol",
2895034d83c4Stim szeto KSTAT_DATA_STRING);
2896034d83c4Stim szeto
2897034d83c4Stim szeto /* ident might not be null terminated */
2898034d83c4Stim szeto len = ilport->ilport_lport->lport_id->ident_length;
2899034d83c4Stim szeto bcopy(ilport->ilport_lport->lport_id->ident,
2900034d83c4Stim szeto ilport->ilport_kstat_tgt_name, len);
2901034d83c4Stim szeto ilport->ilport_kstat_tgt_name[len + 1] = NULL;
2902034d83c4Stim szeto kstat_named_setstr(&ks_tgt->i_tgt_name,
2903034d83c4Stim szeto (const char *)ilport->ilport_kstat_tgt_name);
2904034d83c4Stim szeto kstat_named_setstr(&ks_tgt->i_tgt_alias,
2905034d83c4Stim szeto (const char *)ilport->ilport_lport->lport_alias);
2906034d83c4Stim szeto /* protocol */
2907034d83c4Stim szeto if ((id = ilport->ilport_lport->lport_id->protocol_id) > PROTOCOL_ANY) {
2908034d83c4Stim szeto cmn_err(CE_WARN, "STMF: protocol_id out of bound");
2909034d83c4Stim szeto id = PROTOCOL_ANY;
2910034d83c4Stim szeto }
2911034d83c4Stim szeto kstat_named_setstr(&ks_tgt->i_protocol, protocol_ident[id]);
2912034d83c4Stim szeto kstat_install(ilport->ilport_kstat_info);
2913034d83c4Stim szeto
2914034d83c4Stim szeto /* create kstat lport io */
2915034d83c4Stim szeto bzero(ks_nm, sizeof (ks_nm));
2916034d83c4Stim szeto (void) sprintf(ks_nm, "stmf_tgt_io_%"PRIxPTR"", (uintptr_t)ilport);
2917034d83c4Stim szeto if ((ilport->ilport_kstat_io = kstat_create(STMF_MODULE_NAME, 0,
2918034d83c4Stim szeto ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
2919034d83c4Stim szeto cmn_err(CE_WARN, "STMF: kstat_create target_io failed");
2920034d83c4Stim szeto return;
2921034d83c4Stim szeto }
2922034d83c4Stim szeto mutex_init(&ilport->ilport_kstat_lock, NULL, MUTEX_DRIVER, 0);
2923034d83c4Stim szeto ilport->ilport_kstat_io->ks_lock = &ilport->ilport_kstat_lock;
2924034d83c4Stim szeto kstat_install(ilport->ilport_kstat_io);
2925034d83c4Stim szeto }
2926034d83c4Stim szeto
292745039663SJohn Forte /*
292845039663SJohn Forte * set the asymmetric access state for a logical unit
292945039663SJohn Forte * caller is responsible for establishing SCSI unit attention on
293045039663SJohn Forte * state change
293145039663SJohn Forte */
293245039663SJohn Forte stmf_status_t
stmf_set_lu_access(stmf_lu_t * lu,uint8_t access_state)293345039663SJohn Forte stmf_set_lu_access(stmf_lu_t *lu, uint8_t access_state)
293445039663SJohn Forte {
293545039663SJohn Forte stmf_i_lu_t *ilu;
293645039663SJohn Forte uint8_t *p1, *p2;
293745039663SJohn Forte
293845039663SJohn Forte if ((access_state != STMF_LU_STANDBY) &&
293945039663SJohn Forte (access_state != STMF_LU_ACTIVE)) {
294045039663SJohn Forte return (STMF_INVALID_ARG);
294145039663SJohn Forte }
294245039663SJohn Forte
294345039663SJohn Forte p1 = &lu->lu_id->ident[0];
294445039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
294545039663SJohn Forte if (stmf_state.stmf_inventory_locked) {
294645039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
294745039663SJohn Forte return (STMF_BUSY);
294845039663SJohn Forte }
294945039663SJohn Forte
295045039663SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
295145039663SJohn Forte p2 = &ilu->ilu_lu->lu_id->ident[0];
295245039663SJohn Forte if (bcmp(p1, p2, 16) == 0) {
295345039663SJohn Forte break;
295445039663SJohn Forte }
295545039663SJohn Forte }
295645039663SJohn Forte
295745039663SJohn Forte if (!ilu) {
295845039663SJohn Forte ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
295945039663SJohn Forte } else {
296045039663SJohn Forte /*
296145039663SJohn Forte * We're changing access state on an existing logical unit
296245039663SJohn Forte * Send the proxy registration message for this logical unit
296345039663SJohn Forte * if we're in alua mode.
296445039663SJohn Forte * If the requested state is STMF_LU_ACTIVE, we want to register
296545039663SJohn Forte * this logical unit.
296645039663SJohn Forte * If the requested state is STMF_LU_STANDBY, we're going to
296745039663SJohn Forte * abort all tasks for this logical unit.
296845039663SJohn Forte */
296945039663SJohn Forte if (stmf_state.stmf_alua_state == 1 &&
297045039663SJohn Forte access_state == STMF_LU_ACTIVE) {
297145039663SJohn Forte stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
297245039663SJohn Forte stmf_ic_msg_t *ic_reg_lun;
297345039663SJohn Forte if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
297445039663SJohn Forte lu->lu_lp->lp_alua_support) {
297545039663SJohn Forte ilu->ilu_alua = 1;
297645039663SJohn Forte /* allocate the register message */
297745039663SJohn Forte ic_reg_lun = ic_lun_active_msg_alloc(p1,
297845039663SJohn Forte lu->lu_lp->lp_name,
297945039663SJohn Forte lu->lu_proxy_reg_arg_len,
298045039663SJohn Forte (uint8_t *)lu->lu_proxy_reg_arg,
298145039663SJohn Forte stmf_proxy_msg_id);
298245039663SJohn Forte /* send the message */
298345039663SJohn Forte if (ic_reg_lun) {
298445039663SJohn Forte ic_ret = ic_tx_msg(ic_reg_lun);
298545039663SJohn Forte if (ic_ret == STMF_IC_MSG_SUCCESS) {
298645039663SJohn Forte stmf_proxy_msg_id++;
298745039663SJohn Forte }
298845039663SJohn Forte }
298945039663SJohn Forte }
299045039663SJohn Forte } else if (stmf_state.stmf_alua_state == 1 &&
299145039663SJohn Forte access_state == STMF_LU_STANDBY) {
299245039663SJohn Forte /* abort all tasks for this lu */
299345039663SJohn Forte stmf_task_lu_killall(lu, NULL, STMF_ABORTED);
299445039663SJohn Forte }
299545039663SJohn Forte }
299645039663SJohn Forte
299745039663SJohn Forte ilu->ilu_access = access_state;
299845039663SJohn Forte
299945039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
300045039663SJohn Forte return (STMF_SUCCESS);
300145039663SJohn Forte }
300245039663SJohn Forte
300345039663SJohn Forte
3004fcf3ce44SJohn Forte stmf_status_t
stmf_register_lu(stmf_lu_t * lu)3005fcf3ce44SJohn Forte stmf_register_lu(stmf_lu_t *lu)
3006fcf3ce44SJohn Forte {
3007fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
3008fcf3ce44SJohn Forte uint8_t *p1, *p2;
3009fcf3ce44SJohn Forte stmf_state_change_info_t ssci;
3010fcf3ce44SJohn Forte stmf_id_data_t *luid;
3011fcf3ce44SJohn Forte
3012fcf3ce44SJohn Forte if ((lu->lu_id->ident_type != ID_TYPE_NAA) ||
3013fcf3ce44SJohn Forte (lu->lu_id->ident_length != 16) ||
3014fcf3ce44SJohn Forte ((lu->lu_id->ident[0] & 0xf0) != 0x60)) {
3015fcf3ce44SJohn Forte return (STMF_INVALID_ARG);
3016fcf3ce44SJohn Forte }
3017fcf3ce44SJohn Forte p1 = &lu->lu_id->ident[0];
3018fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
3019fcf3ce44SJohn Forte if (stmf_state.stmf_inventory_locked) {
3020fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3021fcf3ce44SJohn Forte return (STMF_BUSY);
3022fcf3ce44SJohn Forte }
3023fcf3ce44SJohn Forte
3024fcf3ce44SJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
3025fcf3ce44SJohn Forte p2 = &ilu->ilu_lu->lu_id->ident[0];
3026fcf3ce44SJohn Forte if (bcmp(p1, p2, 16) == 0) {
3027fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3028fcf3ce44SJohn Forte return (STMF_ALREADY);
3029fcf3ce44SJohn Forte }
3030fcf3ce44SJohn Forte }
3031fcf3ce44SJohn Forte
3032fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3033fcf3ce44SJohn Forte luid = stmf_lookup_id(&stmf_state.stmf_luid_list,
3034fcf3ce44SJohn Forte lu->lu_id->ident_length, lu->lu_id->ident);
3035fcf3ce44SJohn Forte if (luid) {
3036fcf3ce44SJohn Forte luid->id_pt_to_object = (void *)ilu;
3037fcf3ce44SJohn Forte ilu->ilu_luid = luid;
3038fcf3ce44SJohn Forte }
3039fcf3ce44SJohn Forte ilu->ilu_alias = NULL;
3040fcf3ce44SJohn Forte
3041fcf3ce44SJohn Forte ilu->ilu_next = stmf_state.stmf_ilulist;
3042fcf3ce44SJohn Forte ilu->ilu_prev = NULL;
3043fcf3ce44SJohn Forte if (ilu->ilu_next)
3044fcf3ce44SJohn Forte ilu->ilu_next->ilu_prev = ilu;
3045fcf3ce44SJohn Forte stmf_state.stmf_ilulist = ilu;
3046fcf3ce44SJohn Forte stmf_state.stmf_nlus++;
3047fcf3ce44SJohn Forte if (lu->lu_lp) {
3048fcf3ce44SJohn Forte ((stmf_i_lu_provider_t *)
3049fcf3ce44SJohn Forte (lu->lu_lp->lp_stmf_private))->ilp_nlus++;
3050fcf3ce44SJohn Forte }
3051fcf3ce44SJohn Forte ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
3052fcf3ce44SJohn Forte STMF_EVENT_ALLOC_HANDLE(ilu->ilu_event_hdl);
3053a49dc893SSaso Kiselkov cv_init(&ilu->ilu_offline_pending_cv, NULL, CV_DRIVER, NULL);
3054034d83c4Stim szeto stmf_create_kstat_lu(ilu);
305545039663SJohn Forte /*
305645039663SJohn Forte * register with proxy module if available and logical unit
305745039663SJohn Forte * is in active state
305845039663SJohn Forte */
305945039663SJohn Forte if (stmf_state.stmf_alua_state == 1 &&
306045039663SJohn Forte ilu->ilu_access == STMF_LU_ACTIVE) {
306145039663SJohn Forte stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
306245039663SJohn Forte stmf_ic_msg_t *ic_reg_lun;
306345039663SJohn Forte if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
306445039663SJohn Forte lu->lu_lp->lp_alua_support) {
306545039663SJohn Forte ilu->ilu_alua = 1;
306645039663SJohn Forte /* allocate the register message */
306745039663SJohn Forte ic_reg_lun = ic_reg_lun_msg_alloc(p1,
306845039663SJohn Forte lu->lu_lp->lp_name, lu->lu_proxy_reg_arg_len,
306945039663SJohn Forte (uint8_t *)lu->lu_proxy_reg_arg, stmf_proxy_msg_id);
307045039663SJohn Forte /* send the message */
307145039663SJohn Forte if (ic_reg_lun) {
307245039663SJohn Forte ic_ret = ic_tx_msg(ic_reg_lun);
307345039663SJohn Forte if (ic_ret == STMF_IC_MSG_SUCCESS) {
307445039663SJohn Forte stmf_proxy_msg_id++;
307545039663SJohn Forte }
307645039663SJohn Forte }
307745039663SJohn Forte }
307845039663SJohn Forte }
3079fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3080fcf3ce44SJohn Forte
30814b31676fSsrivijitha dugganapalli /* check the default state for lu */
30824b31676fSsrivijitha dugganapalli if (stmf_state.stmf_default_lu_state == STMF_STATE_OFFLINE) {
30834b31676fSsrivijitha dugganapalli ilu->ilu_prev_state = STMF_STATE_OFFLINE;
30844b31676fSsrivijitha dugganapalli } else {
3085fcf3ce44SJohn Forte ilu->ilu_prev_state = STMF_STATE_ONLINE;
3086fcf3ce44SJohn Forte if (stmf_state.stmf_service_running) {
3087fcf3ce44SJohn Forte ssci.st_rflags = 0;
3088fcf3ce44SJohn Forte ssci.st_additional_info = NULL;
3089fcf3ce44SJohn Forte (void) stmf_ctl(STMF_CMD_LU_ONLINE, lu, &ssci);
3090fcf3ce44SJohn Forte }
30914b31676fSsrivijitha dugganapalli }
3092fcf3ce44SJohn Forte
3093fcf3ce44SJohn Forte /* XXX: Generate event */
3094fcf3ce44SJohn Forte return (STMF_SUCCESS);
3095fcf3ce44SJohn Forte }
3096fcf3ce44SJohn Forte
3097fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_lu(stmf_lu_t * lu)3098fcf3ce44SJohn Forte stmf_deregister_lu(stmf_lu_t *lu)
3099fcf3ce44SJohn Forte {
3100fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
3101fcf3ce44SJohn Forte
3102fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
3103fcf3ce44SJohn Forte if (stmf_state.stmf_inventory_locked) {
3104fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3105fcf3ce44SJohn Forte return (STMF_BUSY);
3106fcf3ce44SJohn Forte }
3107fcf3ce44SJohn Forte ilu = stmf_lookup_lu(lu);
3108fcf3ce44SJohn Forte if (ilu == NULL) {
3109fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3110fcf3ce44SJohn Forte return (STMF_INVALID_ARG);
3111fcf3ce44SJohn Forte }
3112fcf3ce44SJohn Forte if (ilu->ilu_state == STMF_STATE_OFFLINE) {
3113fcf3ce44SJohn Forte ASSERT(ilu->ilu_ntasks == ilu->ilu_ntasks_free);
3114fcf3ce44SJohn Forte while (ilu->ilu_flags & ILU_STALL_DEREGISTER) {
3115fcf3ce44SJohn Forte cv_wait(&stmf_state.stmf_cv, &stmf_state.stmf_lock);
3116fcf3ce44SJohn Forte }
3117fcf3ce44SJohn Forte if (ilu->ilu_ntasks) {
3118fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask, *nitask;
3119fcf3ce44SJohn Forte
3120fcf3ce44SJohn Forte nitask = ilu->ilu_tasks;
3121fcf3ce44SJohn Forte do {
3122fcf3ce44SJohn Forte itask = nitask;
3123fcf3ce44SJohn Forte nitask = itask->itask_lu_next;
3124fcf3ce44SJohn Forte lu->lu_task_free(itask->itask_task);
3125fcf3ce44SJohn Forte stmf_free(itask->itask_task);
3126fcf3ce44SJohn Forte } while (nitask != NULL);
3127fcf3ce44SJohn Forte
3128fcf3ce44SJohn Forte ilu->ilu_tasks = ilu->ilu_free_tasks = NULL;
3129fcf3ce44SJohn Forte ilu->ilu_ntasks = ilu->ilu_ntasks_free = 0;
3130fcf3ce44SJohn Forte }
313145039663SJohn Forte /* de-register with proxy if available */
313245039663SJohn Forte if (ilu->ilu_access == STMF_LU_ACTIVE &&
313345039663SJohn Forte stmf_state.stmf_alua_state == 1) {
313445039663SJohn Forte /* de-register with proxy module */
313545039663SJohn Forte stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
313645039663SJohn Forte stmf_ic_msg_t *ic_dereg_lun;
313745039663SJohn Forte if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
313845039663SJohn Forte lu->lu_lp->lp_alua_support) {
313945039663SJohn Forte ilu->ilu_alua = 1;
314045039663SJohn Forte /* allocate the de-register message */
314145039663SJohn Forte ic_dereg_lun = ic_dereg_lun_msg_alloc(
314245039663SJohn Forte lu->lu_id->ident, lu->lu_lp->lp_name, 0,
314345039663SJohn Forte NULL, stmf_proxy_msg_id);
314445039663SJohn Forte /* send the message */
314545039663SJohn Forte if (ic_dereg_lun) {
314645039663SJohn Forte ic_ret = ic_tx_msg(ic_dereg_lun);
314745039663SJohn Forte if (ic_ret == STMF_IC_MSG_SUCCESS) {
314845039663SJohn Forte stmf_proxy_msg_id++;
314945039663SJohn Forte }
315045039663SJohn Forte }
315145039663SJohn Forte }
315245039663SJohn Forte }
3153fcf3ce44SJohn Forte
3154fcf3ce44SJohn Forte if (ilu->ilu_next)
3155fcf3ce44SJohn Forte ilu->ilu_next->ilu_prev = ilu->ilu_prev;
3156fcf3ce44SJohn Forte if (ilu->ilu_prev)
3157fcf3ce44SJohn Forte ilu->ilu_prev->ilu_next = ilu->ilu_next;
3158fcf3ce44SJohn Forte else
3159fcf3ce44SJohn Forte stmf_state.stmf_ilulist = ilu->ilu_next;
3160fcf3ce44SJohn Forte stmf_state.stmf_nlus--;
3161fcf3ce44SJohn Forte
3162fcf3ce44SJohn Forte if (ilu == stmf_state.stmf_svc_ilu_draining) {
3163fcf3ce44SJohn Forte stmf_state.stmf_svc_ilu_draining = ilu->ilu_next;
3164fcf3ce44SJohn Forte }
3165fcf3ce44SJohn Forte if (ilu == stmf_state.stmf_svc_ilu_timing) {
3166fcf3ce44SJohn Forte stmf_state.stmf_svc_ilu_timing = ilu->ilu_next;
3167fcf3ce44SJohn Forte }
3168fcf3ce44SJohn Forte if (lu->lu_lp) {
3169fcf3ce44SJohn Forte ((stmf_i_lu_provider_t *)
3170fcf3ce44SJohn Forte (lu->lu_lp->lp_stmf_private))->ilp_nlus--;
3171fcf3ce44SJohn Forte }
3172fcf3ce44SJohn Forte if (ilu->ilu_luid) {
3173fcf3ce44SJohn Forte ((stmf_id_data_t *)ilu->ilu_luid)->id_pt_to_object =
3174fcf3ce44SJohn Forte NULL;
3175fcf3ce44SJohn Forte ilu->ilu_luid = NULL;
3176fcf3ce44SJohn Forte }
3177fcf3ce44SJohn Forte STMF_EVENT_FREE_HANDLE(ilu->ilu_event_hdl);
3178fcf3ce44SJohn Forte } else {
3179fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3180fcf3ce44SJohn Forte return (STMF_BUSY);
3181fcf3ce44SJohn Forte }
3182034d83c4Stim szeto if (ilu->ilu_kstat_info) {
3183554c2b16Stim szeto kmem_free(ilu->ilu_kstat_info->ks_data,
3184554c2b16Stim szeto ilu->ilu_kstat_info->ks_data_size);
3185034d83c4Stim szeto kstat_delete(ilu->ilu_kstat_info);
3186034d83c4Stim szeto }
3187034d83c4Stim szeto if (ilu->ilu_kstat_io) {
3188034d83c4Stim szeto kstat_delete(ilu->ilu_kstat_io);
3189034d83c4Stim szeto mutex_destroy(&ilu->ilu_kstat_lock);
3190034d83c4Stim szeto }
3191a49dc893SSaso Kiselkov cv_destroy(&ilu->ilu_offline_pending_cv);
3192fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3193fcf3ce44SJohn Forte return (STMF_SUCCESS);
3194fcf3ce44SJohn Forte }
3195fcf3ce44SJohn Forte
319645039663SJohn Forte void
stmf_set_port_standby(stmf_local_port_t * lport,uint16_t rtpid)319745039663SJohn Forte stmf_set_port_standby(stmf_local_port_t *lport, uint16_t rtpid)
319845039663SJohn Forte {
319945039663SJohn Forte stmf_i_local_port_t *ilport =
320045039663SJohn Forte (stmf_i_local_port_t *)lport->lport_stmf_private;
320145039663SJohn Forte ilport->ilport_rtpid = rtpid;
320245039663SJohn Forte ilport->ilport_standby = 1;
320345039663SJohn Forte }
320445039663SJohn Forte
3205cd36db67SJohn Forte void
stmf_set_port_alua(stmf_local_port_t * lport)3206cd36db67SJohn Forte stmf_set_port_alua(stmf_local_port_t *lport)
3207cd36db67SJohn Forte {
3208cd36db67SJohn Forte stmf_i_local_port_t *ilport =
3209cd36db67SJohn Forte (stmf_i_local_port_t *)lport->lport_stmf_private;
3210cd36db67SJohn Forte ilport->ilport_alua = 1;
3211cd36db67SJohn Forte }
3212cd36db67SJohn Forte
3213fcf3ce44SJohn Forte stmf_status_t
stmf_register_local_port(stmf_local_port_t * lport)3214fcf3ce44SJohn Forte stmf_register_local_port(stmf_local_port_t *lport)
3215fcf3ce44SJohn Forte {
3216fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
3217fcf3ce44SJohn Forte stmf_state_change_info_t ssci;
3218fcf3ce44SJohn Forte int start_workers = 0;
3219fcf3ce44SJohn Forte
3220fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
3221fcf3ce44SJohn Forte if (stmf_state.stmf_inventory_locked) {
3222fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3223fcf3ce44SJohn Forte return (STMF_BUSY);
3224fcf3ce44SJohn Forte }
3225fcf3ce44SJohn Forte ilport = (stmf_i_local_port_t *)lport->lport_stmf_private;
3226fcf3ce44SJohn Forte rw_init(&ilport->ilport_lock, NULL, RW_DRIVER, NULL);
3227fcf3ce44SJohn Forte
3228427fcaf8Stim szeto ilport->ilport_instance =
3229427fcaf8Stim szeto id_alloc_nosleep(stmf_state.stmf_ilport_inst_space);
3230427fcaf8Stim szeto if (ilport->ilport_instance == -1) {
3231427fcaf8Stim szeto mutex_exit(&stmf_state.stmf_lock);
3232427fcaf8Stim szeto return (STMF_FAILURE);
3233427fcaf8Stim szeto }
3234fcf3ce44SJohn Forte ilport->ilport_next = stmf_state.stmf_ilportlist;
3235fcf3ce44SJohn Forte ilport->ilport_prev = NULL;
3236fcf3ce44SJohn Forte if (ilport->ilport_next)
3237fcf3ce44SJohn Forte ilport->ilport_next->ilport_prev = ilport;
3238fcf3ce44SJohn Forte stmf_state.stmf_ilportlist = ilport;
3239fcf3ce44SJohn Forte stmf_state.stmf_nlports++;
3240fcf3ce44SJohn Forte if (lport->lport_pp) {
3241fcf3ce44SJohn Forte ((stmf_i_port_provider_t *)
3242fcf3ce44SJohn Forte (lport->lport_pp->pp_stmf_private))->ipp_npps++;
3243fcf3ce44SJohn Forte }
3244fcf3ce44SJohn Forte ilport->ilport_tg =
3245fcf3ce44SJohn Forte stmf_lookup_group_for_target(lport->lport_id->ident,
3246fcf3ce44SJohn Forte lport->lport_id->ident_length);
324745039663SJohn Forte
324845039663SJohn Forte /*
324945039663SJohn Forte * rtpid will/must be set if this is a standby port
325045039663SJohn Forte * only register ports that are not standby (proxy) ports
3251cd36db67SJohn Forte * and ports that are alua participants (ilport_alua == 1)
325245039663SJohn Forte */
325345039663SJohn Forte if (ilport->ilport_standby == 0) {
32541a5e258fSJosef 'Jeff' Sipek ilport->ilport_rtpid = atomic_inc_16_nv(&stmf_rtpid_counter);
325545039663SJohn Forte }
325645039663SJohn Forte
325745039663SJohn Forte if (stmf_state.stmf_alua_state == 1 &&
3258cd36db67SJohn Forte ilport->ilport_standby == 0 &&
3259cd36db67SJohn Forte ilport->ilport_alua == 1) {
326045039663SJohn Forte stmf_ic_msg_t *ic_reg_port;
326145039663SJohn Forte stmf_ic_msg_status_t ic_ret;
326245039663SJohn Forte stmf_local_port_t *lport;
326345039663SJohn Forte lport = ilport->ilport_lport;
326445039663SJohn Forte ic_reg_port = ic_reg_port_msg_alloc(
326545039663SJohn Forte lport->lport_id, ilport->ilport_rtpid,
326645039663SJohn Forte 0, NULL, stmf_proxy_msg_id);
326745039663SJohn Forte if (ic_reg_port) {
326845039663SJohn Forte ic_ret = ic_tx_msg(ic_reg_port);
326945039663SJohn Forte if (ic_ret == STMF_IC_MSG_SUCCESS) {
327045039663SJohn Forte ilport->ilport_reg_msgid = stmf_proxy_msg_id++;
327145039663SJohn Forte } else {
327245039663SJohn Forte cmn_err(CE_WARN, "error on port registration "
327345039663SJohn Forte "port - %s", ilport->ilport_kstat_tgt_name);
327445039663SJohn Forte }
327545039663SJohn Forte }
327645039663SJohn Forte }
3277fcf3ce44SJohn Forte STMF_EVENT_ALLOC_HANDLE(ilport->ilport_event_hdl);
3278034d83c4Stim szeto stmf_create_kstat_lport(ilport);
3279fcf3ce44SJohn Forte if (stmf_workers_state == STMF_WORKERS_DISABLED) {
3280fcf3ce44SJohn Forte stmf_workers_state = STMF_WORKERS_ENABLING;
3281fcf3ce44SJohn Forte start_workers = 1;
3282fcf3ce44SJohn Forte }
3283fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3284fcf3ce44SJohn Forte
3285fcf3ce44SJohn Forte if (start_workers)
3286fcf3ce44SJohn Forte stmf_worker_init();
3287fcf3ce44SJohn Forte
32884b31676fSsrivijitha dugganapalli /* the default state of LPORT */
32894b31676fSsrivijitha dugganapalli
32904b31676fSsrivijitha dugganapalli if (stmf_state.stmf_default_lport_state == STMF_STATE_OFFLINE) {
32914b31676fSsrivijitha dugganapalli ilport->ilport_prev_state = STMF_STATE_OFFLINE;
32924b31676fSsrivijitha dugganapalli } else {
3293fcf3ce44SJohn Forte ilport->ilport_prev_state = STMF_STATE_ONLINE;
3294fcf3ce44SJohn Forte if (stmf_state.stmf_service_running) {
3295fcf3ce44SJohn Forte ssci.st_rflags = 0;
3296fcf3ce44SJohn Forte ssci.st_additional_info = NULL;
3297fcf3ce44SJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_ONLINE, lport, &ssci);
3298fcf3ce44SJohn Forte }
32994b31676fSsrivijitha dugganapalli }
3300fcf3ce44SJohn Forte
3301fcf3ce44SJohn Forte /* XXX: Generate event */
3302fcf3ce44SJohn Forte return (STMF_SUCCESS);
3303fcf3ce44SJohn Forte }
3304fcf3ce44SJohn Forte
3305fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_local_port(stmf_local_port_t * lport)3306fcf3ce44SJohn Forte stmf_deregister_local_port(stmf_local_port_t *lport)
3307fcf3ce44SJohn Forte {
3308fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
3309fcf3ce44SJohn Forte
3310fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
3311fcf3ce44SJohn Forte if (stmf_state.stmf_inventory_locked) {
3312fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3313fcf3ce44SJohn Forte return (STMF_BUSY);
3314fcf3ce44SJohn Forte }
331545039663SJohn Forte
33166ac72a9cSAlexander Stetsenko /* dequeue all object requests from active queue */
33176ac72a9cSAlexander Stetsenko stmf_svc_kill_obj_requests(lport);
33186ac72a9cSAlexander Stetsenko
3319fcf3ce44SJohn Forte ilport = (stmf_i_local_port_t *)lport->lport_stmf_private;
332045039663SJohn Forte
332145039663SJohn Forte /*
332245039663SJohn Forte * deregister ports that are not standby (proxy)
332345039663SJohn Forte */
332445039663SJohn Forte if (stmf_state.stmf_alua_state == 1 &&
3325cd36db67SJohn Forte ilport->ilport_standby == 0 &&
3326cd36db67SJohn Forte ilport->ilport_alua == 1) {
332745039663SJohn Forte stmf_ic_msg_t *ic_dereg_port;
332845039663SJohn Forte stmf_ic_msg_status_t ic_ret;
332945039663SJohn Forte ic_dereg_port = ic_dereg_port_msg_alloc(
333045039663SJohn Forte lport->lport_id, 0, NULL, stmf_proxy_msg_id);
333145039663SJohn Forte if (ic_dereg_port) {
333245039663SJohn Forte ic_ret = ic_tx_msg(ic_dereg_port);
333345039663SJohn Forte if (ic_ret == STMF_IC_MSG_SUCCESS) {
333445039663SJohn Forte stmf_proxy_msg_id++;
333545039663SJohn Forte }
333645039663SJohn Forte }
333745039663SJohn Forte }
333845039663SJohn Forte
3339fcf3ce44SJohn Forte if (ilport->ilport_nsessions == 0) {
3340fcf3ce44SJohn Forte if (ilport->ilport_next)
3341fcf3ce44SJohn Forte ilport->ilport_next->ilport_prev = ilport->ilport_prev;
3342fcf3ce44SJohn Forte if (ilport->ilport_prev)
3343fcf3ce44SJohn Forte ilport->ilport_prev->ilport_next = ilport->ilport_next;
3344fcf3ce44SJohn Forte else
3345fcf3ce44SJohn Forte stmf_state.stmf_ilportlist = ilport->ilport_next;
3346427fcaf8Stim szeto id_free(stmf_state.stmf_ilport_inst_space,
3347427fcaf8Stim szeto ilport->ilport_instance);
3348fcf3ce44SJohn Forte rw_destroy(&ilport->ilport_lock);
3349fcf3ce44SJohn Forte stmf_state.stmf_nlports--;
3350fcf3ce44SJohn Forte if (lport->lport_pp) {
3351fcf3ce44SJohn Forte ((stmf_i_port_provider_t *)
3352fcf3ce44SJohn Forte (lport->lport_pp->pp_stmf_private))->ipp_npps--;
3353fcf3ce44SJohn Forte }
3354fcf3ce44SJohn Forte ilport->ilport_tg = NULL;
3355fcf3ce44SJohn Forte STMF_EVENT_FREE_HANDLE(ilport->ilport_event_hdl);
3356fcf3ce44SJohn Forte } else {
3357fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3358fcf3ce44SJohn Forte return (STMF_BUSY);
3359fcf3ce44SJohn Forte }
3360034d83c4Stim szeto if (ilport->ilport_kstat_info) {
3361554c2b16Stim szeto kmem_free(ilport->ilport_kstat_info->ks_data,
3362554c2b16Stim szeto ilport->ilport_kstat_info->ks_data_size);
3363034d83c4Stim szeto kstat_delete(ilport->ilport_kstat_info);
3364034d83c4Stim szeto }
3365034d83c4Stim szeto if (ilport->ilport_kstat_io) {
3366034d83c4Stim szeto kstat_delete(ilport->ilport_kstat_io);
3367034d83c4Stim szeto mutex_destroy(&ilport->ilport_kstat_lock);
3368034d83c4Stim szeto }
3369fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3370fcf3ce44SJohn Forte return (STMF_SUCCESS);
3371fcf3ce44SJohn Forte }
3372fcf3ce44SJohn Forte
3373fcf3ce44SJohn Forte /*
3374427fcaf8Stim szeto * Rport id/instance mappings remain valid until STMF is unloaded
3375427fcaf8Stim szeto */
3376427fcaf8Stim szeto static int
stmf_irport_compare(const void * void_irport1,const void * void_irport2)3377427fcaf8Stim szeto stmf_irport_compare(const void *void_irport1, const void *void_irport2)
3378427fcaf8Stim szeto {
3379427fcaf8Stim szeto const stmf_i_remote_port_t *irport1 = void_irport1;
3380427fcaf8Stim szeto const stmf_i_remote_port_t *irport2 = void_irport2;
3381427fcaf8Stim szeto int result;
3382427fcaf8Stim szeto
3383427fcaf8Stim szeto /* Sort by code set then ident */
3384427fcaf8Stim szeto if (irport1->irport_id->code_set <
3385427fcaf8Stim szeto irport2->irport_id->code_set) {
3386427fcaf8Stim szeto return (-1);
3387427fcaf8Stim szeto } else if (irport1->irport_id->code_set >
3388427fcaf8Stim szeto irport2->irport_id->code_set) {
3389427fcaf8Stim szeto return (1);
3390427fcaf8Stim szeto }
3391427fcaf8Stim szeto
3392427fcaf8Stim szeto /* Next by ident length */
3393427fcaf8Stim szeto if (irport1->irport_id->ident_length <
3394427fcaf8Stim szeto irport2->irport_id->ident_length) {
3395427fcaf8Stim szeto return (-1);
3396427fcaf8Stim szeto } else if (irport1->irport_id->ident_length >
3397427fcaf8Stim szeto irport2->irport_id->ident_length) {
3398427fcaf8Stim szeto return (1);
3399427fcaf8Stim szeto }
3400427fcaf8Stim szeto
3401427fcaf8Stim szeto /* Code set and ident length both match, now compare idents */
3402427fcaf8Stim szeto result = memcmp(irport1->irport_id->ident,
3403427fcaf8Stim szeto irport2->irport_id->ident,
3404427fcaf8Stim szeto irport1->irport_id->ident_length);
3405427fcaf8Stim szeto
3406427fcaf8Stim szeto if (result < 0) {
3407427fcaf8Stim szeto return (-1);
3408427fcaf8Stim szeto } else if (result > 0) {
3409427fcaf8Stim szeto return (1);
3410427fcaf8Stim szeto }
3411427fcaf8Stim szeto
3412427fcaf8Stim szeto return (0);
3413427fcaf8Stim szeto }
3414427fcaf8Stim szeto
3415427fcaf8Stim szeto static stmf_i_remote_port_t *
stmf_irport_create(scsi_devid_desc_t * rport_devid)3416427fcaf8Stim szeto stmf_irport_create(scsi_devid_desc_t *rport_devid)
3417427fcaf8Stim szeto {
3418427fcaf8Stim szeto int alloc_len;
3419427fcaf8Stim szeto stmf_i_remote_port_t *irport;
3420427fcaf8Stim szeto
3421427fcaf8Stim szeto /*
3422427fcaf8Stim szeto * Lookup will bump the refcnt if there's an existing rport
3423427fcaf8Stim szeto * context for this identifier.
3424427fcaf8Stim szeto */
3425427fcaf8Stim szeto ASSERT(mutex_owned(&stmf_state.stmf_lock));
3426427fcaf8Stim szeto
3427427fcaf8Stim szeto alloc_len = sizeof (*irport) + sizeof (scsi_devid_desc_t) +
3428427fcaf8Stim szeto rport_devid->ident_length - 1;
3429427fcaf8Stim szeto irport = kmem_zalloc(alloc_len, KM_NOSLEEP);
3430427fcaf8Stim szeto if (irport == NULL) {
3431427fcaf8Stim szeto return (NULL);
3432427fcaf8Stim szeto }
3433427fcaf8Stim szeto
3434427fcaf8Stim szeto irport->irport_instance =
3435427fcaf8Stim szeto id_alloc_nosleep(stmf_state.stmf_irport_inst_space);
3436427fcaf8Stim szeto if (irport->irport_instance == -1) {
3437427fcaf8Stim szeto kmem_free(irport, alloc_len);
3438427fcaf8Stim szeto return (NULL);
3439427fcaf8Stim szeto }
3440427fcaf8Stim szeto
3441427fcaf8Stim szeto irport->irport_id =
3442427fcaf8Stim szeto (struct scsi_devid_desc *)(irport + 1); /* Ptr. Arith. */
3443427fcaf8Stim szeto bcopy(rport_devid, irport->irport_id,
3444427fcaf8Stim szeto sizeof (scsi_devid_desc_t) + rport_devid->ident_length - 1);
3445427fcaf8Stim szeto irport->irport_refcnt = 1;
3446427fcaf8Stim szeto mutex_init(&irport->irport_mutex, NULL, MUTEX_DEFAULT, NULL);
3447427fcaf8Stim szeto
3448427fcaf8Stim szeto return (irport);
3449427fcaf8Stim szeto }
3450427fcaf8Stim szeto
3451427fcaf8Stim szeto static void
stmf_irport_destroy(stmf_i_remote_port_t * irport)3452427fcaf8Stim szeto stmf_irport_destroy(stmf_i_remote_port_t *irport)
3453427fcaf8Stim szeto {
3454427fcaf8Stim szeto id_free(stmf_state.stmf_irport_inst_space, irport->irport_instance);
3455427fcaf8Stim szeto mutex_destroy(&irport->irport_mutex);
3456427fcaf8Stim szeto kmem_free(irport, sizeof (*irport) + sizeof (scsi_devid_desc_t) +
3457427fcaf8Stim szeto irport->irport_id->ident_length - 1);
3458427fcaf8Stim szeto }
3459427fcaf8Stim szeto
3460427fcaf8Stim szeto static stmf_i_remote_port_t *
stmf_irport_register(scsi_devid_desc_t * rport_devid)3461427fcaf8Stim szeto stmf_irport_register(scsi_devid_desc_t *rport_devid)
3462427fcaf8Stim szeto {
3463427fcaf8Stim szeto stmf_i_remote_port_t *irport;
3464427fcaf8Stim szeto
3465427fcaf8Stim szeto mutex_enter(&stmf_state.stmf_lock);
3466427fcaf8Stim szeto
3467427fcaf8Stim szeto /*
3468427fcaf8Stim szeto * Lookup will bump the refcnt if there's an existing rport
3469427fcaf8Stim szeto * context for this identifier.
3470427fcaf8Stim szeto */
3471427fcaf8Stim szeto if ((irport = stmf_irport_lookup_locked(rport_devid)) != NULL) {
3472427fcaf8Stim szeto mutex_exit(&stmf_state.stmf_lock);
3473427fcaf8Stim szeto return (irport);
3474427fcaf8Stim szeto }
3475427fcaf8Stim szeto
3476427fcaf8Stim szeto irport = stmf_irport_create(rport_devid);
3477427fcaf8Stim szeto if (irport == NULL) {
3478427fcaf8Stim szeto mutex_exit(&stmf_state.stmf_lock);
3479427fcaf8Stim szeto return (NULL);
3480427fcaf8Stim szeto }
3481427fcaf8Stim szeto
3482427fcaf8Stim szeto avl_add(&stmf_state.stmf_irportlist, irport);
3483427fcaf8Stim szeto mutex_exit(&stmf_state.stmf_lock);
3484427fcaf8Stim szeto
3485427fcaf8Stim szeto return (irport);
3486427fcaf8Stim szeto }
3487427fcaf8Stim szeto
3488427fcaf8Stim szeto static stmf_i_remote_port_t *
stmf_irport_lookup_locked(scsi_devid_desc_t * rport_devid)3489427fcaf8Stim szeto stmf_irport_lookup_locked(scsi_devid_desc_t *rport_devid)
3490427fcaf8Stim szeto {
3491427fcaf8Stim szeto stmf_i_remote_port_t *irport;
3492427fcaf8Stim szeto stmf_i_remote_port_t tmp_irport;
3493427fcaf8Stim szeto
3494427fcaf8Stim szeto ASSERT(mutex_owned(&stmf_state.stmf_lock));
3495427fcaf8Stim szeto tmp_irport.irport_id = rport_devid;
3496427fcaf8Stim szeto irport = avl_find(&stmf_state.stmf_irportlist, &tmp_irport, NULL);
3497427fcaf8Stim szeto if (irport != NULL) {
3498427fcaf8Stim szeto mutex_enter(&irport->irport_mutex);
3499427fcaf8Stim szeto irport->irport_refcnt++;
3500427fcaf8Stim szeto mutex_exit(&irport->irport_mutex);
3501427fcaf8Stim szeto }
3502427fcaf8Stim szeto
3503427fcaf8Stim szeto return (irport);
3504427fcaf8Stim szeto }
3505427fcaf8Stim szeto
3506427fcaf8Stim szeto static void
stmf_irport_deregister(stmf_i_remote_port_t * irport)3507427fcaf8Stim szeto stmf_irport_deregister(stmf_i_remote_port_t *irport)
3508427fcaf8Stim szeto {
3509427fcaf8Stim szeto /*
3510427fcaf8Stim szeto * If we were actually going to remove unreferenced remote ports
3511427fcaf8Stim szeto * we would want to acquire stmf_state.stmf_lock before getting
3512427fcaf8Stim szeto * the irport mutex.
3513427fcaf8Stim szeto *
3514427fcaf8Stim szeto * Instead we're just going to leave it there even if unreferenced.
3515427fcaf8Stim szeto */
3516427fcaf8Stim szeto mutex_enter(&irport->irport_mutex);
3517427fcaf8Stim szeto irport->irport_refcnt--;
3518427fcaf8Stim szeto mutex_exit(&irport->irport_mutex);
3519427fcaf8Stim szeto }
3520427fcaf8Stim szeto
3521427fcaf8Stim szeto /*
3522fcf3ce44SJohn Forte * Port provider has to make sure that register/deregister session and
3523fcf3ce44SJohn Forte * port are serialized calls.
3524fcf3ce44SJohn Forte */
3525fcf3ce44SJohn Forte stmf_status_t
stmf_register_scsi_session(stmf_local_port_t * lport,stmf_scsi_session_t * ss)3526fcf3ce44SJohn Forte stmf_register_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss)
3527fcf3ce44SJohn Forte {
3528fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
3529fcf3ce44SJohn Forte stmf_i_local_port_t *ilport = (stmf_i_local_port_t *)
3530fcf3ce44SJohn Forte lport->lport_stmf_private;
3531fcf3ce44SJohn Forte uint8_t lun[8];
3532fcf3ce44SJohn Forte
3533fcf3ce44SJohn Forte /*
3534fcf3ce44SJohn Forte * Port state has to be online to register a scsi session. It is
3535fcf3ce44SJohn Forte * possible that we started an offline operation and a new SCSI
3536fcf3ce44SJohn Forte * session started at the same time (in that case also we are going
3537fcf3ce44SJohn Forte * to fail the registeration). But any other state is simply
3538fcf3ce44SJohn Forte * a bad port provider implementation.
3539fcf3ce44SJohn Forte */
3540fcf3ce44SJohn Forte if (ilport->ilport_state != STMF_STATE_ONLINE) {
3541fcf3ce44SJohn Forte if (ilport->ilport_state != STMF_STATE_OFFLINING) {
3542fcf3ce44SJohn Forte stmf_trace(lport->lport_alias, "Port is trying to "
3543fcf3ce44SJohn Forte "register a session while the state is neither "
3544fcf3ce44SJohn Forte "online nor offlining");
3545fcf3ce44SJohn Forte }
3546fcf3ce44SJohn Forte return (STMF_FAILURE);
3547fcf3ce44SJohn Forte }
3548fcf3ce44SJohn Forte bzero(lun, 8);
3549fcf3ce44SJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3550427fcaf8Stim szeto if ((iss->iss_irport = stmf_irport_register(ss->ss_rport_id)) == NULL) {
3551427fcaf8Stim szeto stmf_trace(lport->lport_alias, "Could not register "
3552427fcaf8Stim szeto "remote port during session registration");
3553427fcaf8Stim szeto return (STMF_FAILURE);
3554427fcaf8Stim szeto }
3555427fcaf8Stim szeto
3556fcf3ce44SJohn Forte iss->iss_flags |= ISS_BEING_CREATED;
3557fcf3ce44SJohn Forte
3558716c1805SNattuvetty Bhavyan if (ss->ss_rport == NULL) {
3559716c1805SNattuvetty Bhavyan iss->iss_flags |= ISS_NULL_TPTID;
3560716c1805SNattuvetty Bhavyan ss->ss_rport = stmf_scsilib_devid_to_remote_port(
3561716c1805SNattuvetty Bhavyan ss->ss_rport_id);
3562716c1805SNattuvetty Bhavyan if (ss->ss_rport == NULL) {
3563716c1805SNattuvetty Bhavyan iss->iss_flags &= ~(ISS_NULL_TPTID | ISS_BEING_CREATED);
3564716c1805SNattuvetty Bhavyan stmf_trace(lport->lport_alias, "Device id to "
3565716c1805SNattuvetty Bhavyan "remote port conversion failed");
3566716c1805SNattuvetty Bhavyan return (STMF_FAILURE);
3567716c1805SNattuvetty Bhavyan }
3568716c1805SNattuvetty Bhavyan } else {
3569716c1805SNattuvetty Bhavyan if (!stmf_scsilib_tptid_validate(ss->ss_rport->rport_tptid,
3570716c1805SNattuvetty Bhavyan ss->ss_rport->rport_tptid_sz, NULL)) {
3571716c1805SNattuvetty Bhavyan iss->iss_flags &= ~ISS_BEING_CREATED;
3572716c1805SNattuvetty Bhavyan stmf_trace(lport->lport_alias, "Remote port "
3573716c1805SNattuvetty Bhavyan "transport id validation failed");
3574716c1805SNattuvetty Bhavyan return (STMF_FAILURE);
3575716c1805SNattuvetty Bhavyan }
3576716c1805SNattuvetty Bhavyan }
3577716c1805SNattuvetty Bhavyan
3578fcf3ce44SJohn Forte /* sessions use the ilport_lock. No separate lock is required */
3579fcf3ce44SJohn Forte iss->iss_lockp = &ilport->ilport_lock;
3580fcf3ce44SJohn Forte
3581780c822cStim szeto if (iss->iss_sm != NULL)
3582780c822cStim szeto cmn_err(CE_PANIC, "create lun map called with non NULL map");
3583780c822cStim szeto iss->iss_sm = (stmf_lun_map_t *)kmem_zalloc(sizeof (stmf_lun_map_t),
3584780c822cStim szeto KM_SLEEP);
3585780c822cStim szeto
3586780c822cStim szeto mutex_enter(&stmf_state.stmf_lock);
3587fcf3ce44SJohn Forte rw_enter(&ilport->ilport_lock, RW_WRITER);
3588780c822cStim szeto (void) stmf_session_create_lun_map(ilport, iss);
3589fcf3ce44SJohn Forte ilport->ilport_nsessions++;
3590fcf3ce44SJohn Forte iss->iss_next = ilport->ilport_ss_list;
3591fcf3ce44SJohn Forte ilport->ilport_ss_list = iss;
3592fcf3ce44SJohn Forte rw_exit(&ilport->ilport_lock);
3593780c822cStim szeto mutex_exit(&stmf_state.stmf_lock);
3594fcf3ce44SJohn Forte
3595fcf3ce44SJohn Forte iss->iss_creation_time = ddi_get_time();
35961a5e258fSJosef 'Jeff' Sipek ss->ss_session_id = atomic_inc_64_nv(&stmf_session_counter);
3597fcf3ce44SJohn Forte iss->iss_flags &= ~ISS_BEING_CREATED;
359845039663SJohn Forte /* XXX should we remove ISS_LUN_INVENTORY_CHANGED on new session? */
359945039663SJohn Forte iss->iss_flags &= ~ISS_LUN_INVENTORY_CHANGED;
3600e17f3b22Stim szeto DTRACE_PROBE2(session__online, stmf_local_port_t *, lport,
3601e17f3b22Stim szeto stmf_scsi_session_t *, ss);
3602fcf3ce44SJohn Forte return (STMF_SUCCESS);
3603fcf3ce44SJohn Forte }
3604fcf3ce44SJohn Forte
3605fcf3ce44SJohn Forte void
stmf_deregister_scsi_session(stmf_local_port_t * lport,stmf_scsi_session_t * ss)3606fcf3ce44SJohn Forte stmf_deregister_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss)
3607fcf3ce44SJohn Forte {
3608fcf3ce44SJohn Forte stmf_i_local_port_t *ilport = (stmf_i_local_port_t *)
3609fcf3ce44SJohn Forte lport->lport_stmf_private;
3610fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss, **ppss;
3611fcf3ce44SJohn Forte int found = 0;
361245039663SJohn Forte stmf_ic_msg_t *ic_session_dereg;
361345039663SJohn Forte stmf_status_t ic_ret = STMF_FAILURE;
3614fcf3ce44SJohn Forte
3615e17f3b22Stim szeto DTRACE_PROBE2(session__offline, stmf_local_port_t *, lport,
3616e17f3b22Stim szeto stmf_scsi_session_t *, ss);
3617e17f3b22Stim szeto
3618fcf3ce44SJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3619fcf3ce44SJohn Forte if (ss->ss_rport_alias) {
3620fcf3ce44SJohn Forte ss->ss_rport_alias = NULL;
3621fcf3ce44SJohn Forte }
3622fcf3ce44SJohn Forte
3623fcf3ce44SJohn Forte try_dereg_ss_again:
3624fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
3625fcf3ce44SJohn Forte atomic_and_32(&iss->iss_flags,
3626fcf3ce44SJohn Forte ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS));
3627fcf3ce44SJohn Forte if (iss->iss_flags & ISS_EVENT_ACTIVE) {
3628fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3629fcf3ce44SJohn Forte delay(1);
3630fcf3ce44SJohn Forte goto try_dereg_ss_again;
3631fcf3ce44SJohn Forte }
363245039663SJohn Forte
363345039663SJohn Forte /* dereg proxy session if not standby port */
3634cd36db67SJohn Forte if (stmf_state.stmf_alua_state == 1 &&
3635cd36db67SJohn Forte ilport->ilport_standby == 0 &&
3636cd36db67SJohn Forte ilport->ilport_alua == 1) {
363745039663SJohn Forte ic_session_dereg = ic_session_dereg_msg_alloc(
363845039663SJohn Forte ss, stmf_proxy_msg_id);
363945039663SJohn Forte if (ic_session_dereg) {
364045039663SJohn Forte ic_ret = ic_tx_msg(ic_session_dereg);
364145039663SJohn Forte if (ic_ret == STMF_IC_MSG_SUCCESS) {
364245039663SJohn Forte stmf_proxy_msg_id++;
364345039663SJohn Forte }
364445039663SJohn Forte }
364545039663SJohn Forte }
364645039663SJohn Forte
3647fcf3ce44SJohn Forte rw_enter(&ilport->ilport_lock, RW_WRITER);
3648fcf3ce44SJohn Forte for (ppss = &ilport->ilport_ss_list; *ppss != NULL;
3649fcf3ce44SJohn Forte ppss = &((*ppss)->iss_next)) {
3650fcf3ce44SJohn Forte if (iss == (*ppss)) {
3651fcf3ce44SJohn Forte *ppss = (*ppss)->iss_next;
3652fcf3ce44SJohn Forte found = 1;
3653fcf3ce44SJohn Forte break;
3654fcf3ce44SJohn Forte }
3655fcf3ce44SJohn Forte }
3656fcf3ce44SJohn Forte if (!found) {
3657fcf3ce44SJohn Forte cmn_err(CE_PANIC, "Deregister session called for non existent"
3658fcf3ce44SJohn Forte " session");
3659fcf3ce44SJohn Forte }
3660fcf3ce44SJohn Forte ilport->ilport_nsessions--;
3661fcf3ce44SJohn Forte
3662427fcaf8Stim szeto stmf_irport_deregister(iss->iss_irport);
3663fcf3ce44SJohn Forte (void) stmf_session_destroy_lun_map(ilport, iss);
3664780c822cStim szeto rw_exit(&ilport->ilport_lock);
3665780c822cStim szeto mutex_exit(&stmf_state.stmf_lock);
3666716c1805SNattuvetty Bhavyan
3667716c1805SNattuvetty Bhavyan if (iss->iss_flags & ISS_NULL_TPTID) {
3668716c1805SNattuvetty Bhavyan stmf_remote_port_free(ss->ss_rport);
3669716c1805SNattuvetty Bhavyan }
3670fcf3ce44SJohn Forte }
3671fcf3ce44SJohn Forte
3672fcf3ce44SJohn Forte stmf_i_scsi_session_t *
stmf_session_id_to_issptr(uint64_t session_id,int stay_locked)3673fcf3ce44SJohn Forte stmf_session_id_to_issptr(uint64_t session_id, int stay_locked)
3674fcf3ce44SJohn Forte {
3675fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
3676fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
3677fcf3ce44SJohn Forte
3678fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
3679fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
3680fcf3ce44SJohn Forte ilport = ilport->ilport_next) {
3681fcf3ce44SJohn Forte rw_enter(&ilport->ilport_lock, RW_WRITER);
3682fcf3ce44SJohn Forte for (iss = ilport->ilport_ss_list; iss != NULL;
3683fcf3ce44SJohn Forte iss = iss->iss_next) {
3684fcf3ce44SJohn Forte if (iss->iss_ss->ss_session_id == session_id) {
3685fcf3ce44SJohn Forte if (!stay_locked)
3686fcf3ce44SJohn Forte rw_exit(&ilport->ilport_lock);
3687fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3688fcf3ce44SJohn Forte return (iss);
3689fcf3ce44SJohn Forte }
3690fcf3ce44SJohn Forte }
3691fcf3ce44SJohn Forte rw_exit(&ilport->ilport_lock);
3692fcf3ce44SJohn Forte }
3693fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3694fcf3ce44SJohn Forte return (NULL);
3695fcf3ce44SJohn Forte }
3696fcf3ce44SJohn Forte
3697fcf3ce44SJohn Forte void
stmf_release_itl_handle(stmf_lu_t * lu,stmf_itl_data_t * itl)3698fcf3ce44SJohn Forte stmf_release_itl_handle(stmf_lu_t *lu, stmf_itl_data_t *itl)
3699fcf3ce44SJohn Forte {
3700fcf3ce44SJohn Forte stmf_itl_data_t **itlpp;
3701fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
3702fcf3ce44SJohn Forte
3703fcf3ce44SJohn Forte ASSERT(itl->itl_flags & STMF_ITL_BEING_TERMINATED);
3704fcf3ce44SJohn Forte
3705fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3706fcf3ce44SJohn Forte mutex_enter(&ilu->ilu_task_lock);
3707fcf3ce44SJohn Forte for (itlpp = &ilu->ilu_itl_list; (*itlpp) != NULL;
3708fcf3ce44SJohn Forte itlpp = &(*itlpp)->itl_next) {
3709fcf3ce44SJohn Forte if ((*itlpp) == itl)
3710fcf3ce44SJohn Forte break;
3711fcf3ce44SJohn Forte }
3712fcf3ce44SJohn Forte ASSERT((*itlpp) != NULL);
3713fcf3ce44SJohn Forte *itlpp = itl->itl_next;
3714fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
3715fcf3ce44SJohn Forte lu->lu_abort(lu, STMF_LU_ITL_HANDLE_REMOVED, itl->itl_handle,
3716fcf3ce44SJohn Forte (uint32_t)itl->itl_hdlrm_reason);
3717427fcaf8Stim szeto
3718fcf3ce44SJohn Forte kmem_free(itl, sizeof (*itl));
3719fcf3ce44SJohn Forte }
3720fcf3ce44SJohn Forte
3721fcf3ce44SJohn 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)3722fcf3ce44SJohn Forte stmf_register_itl_handle(stmf_lu_t *lu, uint8_t *lun,
3723fcf3ce44SJohn Forte stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle)
3724fcf3ce44SJohn Forte {
3725fcf3ce44SJohn Forte stmf_itl_data_t *itl;
3726fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
3727fcf3ce44SJohn Forte stmf_lun_map_ent_t *lun_map_ent;
3728fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
3729fcf3ce44SJohn Forte uint16_t n;
3730fcf3ce44SJohn Forte
3731fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3732fcf3ce44SJohn Forte if (ss == NULL) {
3733fcf3ce44SJohn Forte iss = stmf_session_id_to_issptr(session_id, 1);
3734fcf3ce44SJohn Forte if (iss == NULL)
3735fcf3ce44SJohn Forte return (STMF_NOT_FOUND);
3736fcf3ce44SJohn Forte } else {
3737fcf3ce44SJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3738fcf3ce44SJohn Forte }
3739fcf3ce44SJohn Forte
3740a8e2ef8fStim szeto mutex_enter(&stmf_state.stmf_lock);
3741427fcaf8Stim szeto rw_enter(iss->iss_lockp, RW_WRITER);
3742fcf3ce44SJohn Forte n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
3743fcf3ce44SJohn Forte lun_map_ent = (stmf_lun_map_ent_t *)
3744fcf3ce44SJohn Forte stmf_get_ent_from_map(iss->iss_sm, n);
3745fcf3ce44SJohn Forte if ((lun_map_ent == NULL) || (lun_map_ent->ent_lu != lu)) {
3746fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
3747a8e2ef8fStim szeto mutex_exit(&stmf_state.stmf_lock);
3748fcf3ce44SJohn Forte return (STMF_NOT_FOUND);
3749fcf3ce44SJohn Forte }
3750fcf3ce44SJohn Forte if (lun_map_ent->ent_itl_datap != NULL) {
3751fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
3752a8e2ef8fStim szeto mutex_exit(&stmf_state.stmf_lock);
3753fcf3ce44SJohn Forte return (STMF_ALREADY);
3754fcf3ce44SJohn Forte }
3755fcf3ce44SJohn Forte
3756fcf3ce44SJohn Forte itl = (stmf_itl_data_t *)kmem_zalloc(sizeof (*itl), KM_NOSLEEP);
3757fcf3ce44SJohn Forte if (itl == NULL) {
3758fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
3759a8e2ef8fStim szeto mutex_exit(&stmf_state.stmf_lock);
3760fcf3ce44SJohn Forte return (STMF_ALLOC_FAILURE);
3761fcf3ce44SJohn Forte }
3762fcf3ce44SJohn Forte
3763427fcaf8Stim szeto itl->itl_ilu = ilu;
3764427fcaf8Stim szeto itl->itl_session = iss;
3765fcf3ce44SJohn Forte itl->itl_counter = 1;
3766fcf3ce44SJohn Forte itl->itl_lun = n;
3767fcf3ce44SJohn Forte itl->itl_handle = itl_handle;
3768427fcaf8Stim szeto
3769fcf3ce44SJohn Forte mutex_enter(&ilu->ilu_task_lock);
3770fcf3ce44SJohn Forte itl->itl_next = ilu->ilu_itl_list;
3771fcf3ce44SJohn Forte ilu->ilu_itl_list = itl;
3772fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
3773fcf3ce44SJohn Forte lun_map_ent->ent_itl_datap = itl;
3774fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
3775a8e2ef8fStim szeto mutex_exit(&stmf_state.stmf_lock);
3776fcf3ce44SJohn Forte
3777fcf3ce44SJohn Forte return (STMF_SUCCESS);
3778fcf3ce44SJohn Forte }
3779fcf3ce44SJohn Forte
3780fcf3ce44SJohn Forte void
stmf_do_itl_dereg(stmf_lu_t * lu,stmf_itl_data_t * itl,uint8_t hdlrm_reason)3781fcf3ce44SJohn Forte stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl, uint8_t hdlrm_reason)
3782fcf3ce44SJohn Forte {
3783fcf3ce44SJohn Forte uint8_t old, new;
3784fcf3ce44SJohn Forte
3785fcf3ce44SJohn Forte do {
3786fcf3ce44SJohn Forte old = new = itl->itl_flags;
3787fcf3ce44SJohn Forte if (old & STMF_ITL_BEING_TERMINATED)
3788fcf3ce44SJohn Forte return;
3789fcf3ce44SJohn Forte new |= STMF_ITL_BEING_TERMINATED;
3790fcf3ce44SJohn Forte } while (atomic_cas_8(&itl->itl_flags, old, new) != old);
3791fcf3ce44SJohn Forte itl->itl_hdlrm_reason = hdlrm_reason;
3792fcf3ce44SJohn Forte
3793fcf3ce44SJohn Forte ASSERT(itl->itl_counter);
3794fcf3ce44SJohn Forte
37951a5e258fSJosef 'Jeff' Sipek if (atomic_dec_32_nv(&itl->itl_counter))
3796fcf3ce44SJohn Forte return;
3797fcf3ce44SJohn Forte
3798fcf3ce44SJohn Forte stmf_release_itl_handle(lu, itl);
3799fcf3ce44SJohn Forte }
3800fcf3ce44SJohn Forte
3801fcf3ce44SJohn Forte stmf_status_t
stmf_deregister_all_lu_itl_handles(stmf_lu_t * lu)3802fcf3ce44SJohn Forte stmf_deregister_all_lu_itl_handles(stmf_lu_t *lu)
3803fcf3ce44SJohn Forte {
3804fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
3805fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
3806fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
3807fcf3ce44SJohn Forte stmf_lun_map_t *lm;
3808fcf3ce44SJohn Forte stmf_lun_map_ent_t *ent;
3809fcf3ce44SJohn Forte uint32_t nmaps, nu;
3810fcf3ce44SJohn Forte stmf_itl_data_t **itl_list;
3811fcf3ce44SJohn Forte int i;
3812fcf3ce44SJohn Forte
3813fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3814fcf3ce44SJohn Forte
3815fcf3ce44SJohn Forte dereg_itl_start:;
3816fcf3ce44SJohn Forte nmaps = ilu->ilu_ref_cnt;
3817fcf3ce44SJohn Forte if (nmaps == 0)
3818fcf3ce44SJohn Forte return (STMF_NOT_FOUND);
3819fcf3ce44SJohn Forte itl_list = (stmf_itl_data_t **)kmem_zalloc(
3820fcf3ce44SJohn Forte nmaps * sizeof (stmf_itl_data_t *), KM_SLEEP);
3821fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
3822fcf3ce44SJohn Forte if (nmaps != ilu->ilu_ref_cnt) {
3823fcf3ce44SJohn Forte /* Something changed, start all over */
3824fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3825fcf3ce44SJohn Forte kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
3826fcf3ce44SJohn Forte goto dereg_itl_start;
3827fcf3ce44SJohn Forte }
3828fcf3ce44SJohn Forte nu = 0;
3829fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
3830fcf3ce44SJohn Forte ilport = ilport->ilport_next) {
3831fcf3ce44SJohn Forte rw_enter(&ilport->ilport_lock, RW_WRITER);
3832fcf3ce44SJohn Forte for (iss = ilport->ilport_ss_list; iss != NULL;
3833fcf3ce44SJohn Forte iss = iss->iss_next) {
3834fcf3ce44SJohn Forte lm = iss->iss_sm;
3835fcf3ce44SJohn Forte if (!lm)
3836fcf3ce44SJohn Forte continue;
3837fcf3ce44SJohn Forte for (i = 0; i < lm->lm_nentries; i++) {
3838fcf3ce44SJohn Forte if (lm->lm_plus[i] == NULL)
3839fcf3ce44SJohn Forte continue;
3840fcf3ce44SJohn Forte ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
3841fcf3ce44SJohn Forte if ((ent->ent_lu == lu) &&
3842fcf3ce44SJohn Forte (ent->ent_itl_datap)) {
3843fcf3ce44SJohn Forte itl_list[nu++] = ent->ent_itl_datap;
3844fcf3ce44SJohn Forte ent->ent_itl_datap = NULL;
3845fcf3ce44SJohn Forte if (nu == nmaps) {
3846fcf3ce44SJohn Forte rw_exit(&ilport->ilport_lock);
3847fcf3ce44SJohn Forte goto dai_scan_done;
3848fcf3ce44SJohn Forte }
3849fcf3ce44SJohn Forte }
3850fcf3ce44SJohn Forte } /* lun table for a session */
3851fcf3ce44SJohn Forte } /* sessions */
3852fcf3ce44SJohn Forte rw_exit(&ilport->ilport_lock);
3853fcf3ce44SJohn Forte } /* ports */
3854fcf3ce44SJohn Forte
3855fcf3ce44SJohn Forte dai_scan_done:
3856fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
3857fcf3ce44SJohn Forte
3858fcf3ce44SJohn Forte for (i = 0; i < nu; i++) {
3859fcf3ce44SJohn Forte stmf_do_itl_dereg(lu, itl_list[i],
3860fcf3ce44SJohn Forte STMF_ITL_REASON_DEREG_REQUEST);
3861fcf3ce44SJohn Forte }
3862fcf3ce44SJohn Forte kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
3863fcf3ce44SJohn Forte
3864fcf3ce44SJohn Forte return (STMF_SUCCESS);
3865fcf3ce44SJohn Forte }
3866fcf3ce44SJohn Forte
3867fcf3ce44SJohn Forte stmf_status_t
stmf_get_itl_handle(stmf_lu_t * lu,uint8_t * lun,stmf_scsi_session_t * ss,uint64_t session_id,void ** itl_handle_retp)3868fcf3ce44SJohn Forte stmf_get_itl_handle(stmf_lu_t *lu, uint8_t *lun, stmf_scsi_session_t *ss,
3869fcf3ce44SJohn Forte uint64_t session_id, void **itl_handle_retp)
3870fcf3ce44SJohn Forte {
3871fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
3872fcf3ce44SJohn Forte stmf_lun_map_ent_t *ent;
3873fcf3ce44SJohn Forte stmf_lun_map_t *lm;
3874fcf3ce44SJohn Forte stmf_status_t ret;
3875fcf3ce44SJohn Forte int i;
3876fcf3ce44SJohn Forte uint16_t n;
3877fcf3ce44SJohn Forte
3878fcf3ce44SJohn Forte if (ss == NULL) {
3879fcf3ce44SJohn Forte iss = stmf_session_id_to_issptr(session_id, 1);
3880fcf3ce44SJohn Forte if (iss == NULL)
3881fcf3ce44SJohn Forte return (STMF_NOT_FOUND);
3882fcf3ce44SJohn Forte } else {
3883fcf3ce44SJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3884fcf3ce44SJohn Forte rw_enter(iss->iss_lockp, RW_WRITER);
3885fcf3ce44SJohn Forte }
3886fcf3ce44SJohn Forte
3887fcf3ce44SJohn Forte ent = NULL;
3888fcf3ce44SJohn Forte if (lun == NULL) {
3889fcf3ce44SJohn Forte lm = iss->iss_sm;
3890fcf3ce44SJohn Forte for (i = 0; i < lm->lm_nentries; i++) {
3891fcf3ce44SJohn Forte if (lm->lm_plus[i] == NULL)
3892fcf3ce44SJohn Forte continue;
3893fcf3ce44SJohn Forte ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
3894fcf3ce44SJohn Forte if (ent->ent_lu == lu)
3895fcf3ce44SJohn Forte break;
3896fcf3ce44SJohn Forte }
3897fcf3ce44SJohn Forte } else {
3898fcf3ce44SJohn Forte n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
3899fcf3ce44SJohn Forte ent = (stmf_lun_map_ent_t *)
3900fcf3ce44SJohn Forte stmf_get_ent_from_map(iss->iss_sm, n);
3901fcf3ce44SJohn Forte if (lu && (ent->ent_lu != lu))
3902fcf3ce44SJohn Forte ent = NULL;
3903fcf3ce44SJohn Forte }
3904fcf3ce44SJohn Forte if (ent && ent->ent_itl_datap) {
3905fcf3ce44SJohn Forte *itl_handle_retp = ent->ent_itl_datap->itl_handle;
3906fcf3ce44SJohn Forte ret = STMF_SUCCESS;
3907fcf3ce44SJohn Forte } else {
3908fcf3ce44SJohn Forte ret = STMF_NOT_FOUND;
3909fcf3ce44SJohn Forte }
3910fcf3ce44SJohn Forte
3911fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
3912fcf3ce44SJohn Forte return (ret);
3913fcf3ce44SJohn Forte }
3914fcf3ce44SJohn Forte
3915fcf3ce44SJohn Forte stmf_data_buf_t *
stmf_alloc_dbuf(scsi_task_t * task,uint32_t size,uint32_t * pminsize,uint32_t flags)3916fcf3ce44SJohn Forte stmf_alloc_dbuf(scsi_task_t *task, uint32_t size, uint32_t *pminsize,
3917fcf3ce44SJohn Forte uint32_t flags)
3918fcf3ce44SJohn Forte {
3919fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
3920fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
3921fcf3ce44SJohn Forte stmf_local_port_t *lport = task->task_lport;
3922fcf3ce44SJohn Forte stmf_data_buf_t *dbuf;
3923fcf3ce44SJohn Forte uint8_t ndx;
3924fcf3ce44SJohn Forte
3925fcf3ce44SJohn Forte ndx = stmf_first_zero[itask->itask_allocated_buf_map];
3926fcf3ce44SJohn Forte if (ndx == 0xff)
3927fcf3ce44SJohn Forte return (NULL);
3928fcf3ce44SJohn Forte dbuf = itask->itask_dbufs[ndx] = lport->lport_ds->ds_alloc_data_buf(
3929fcf3ce44SJohn Forte task, size, pminsize, flags);
3930fcf3ce44SJohn Forte if (dbuf) {
3931fcf3ce44SJohn Forte task->task_cur_nbufs++;
3932fcf3ce44SJohn Forte itask->itask_allocated_buf_map |= (1 << ndx);
393340c3e8ffSJohn Forte dbuf->db_flags &= ~DB_LPORT_XFER_ACTIVE;
3934fcf3ce44SJohn Forte dbuf->db_handle = ndx;
3935fcf3ce44SJohn Forte return (dbuf);
3936fcf3ce44SJohn Forte }
3937fcf3ce44SJohn Forte
3938fcf3ce44SJohn Forte return (NULL);
3939fcf3ce44SJohn Forte }
3940fcf3ce44SJohn Forte
39413fb517f7SJames Moore stmf_status_t
stmf_setup_dbuf(scsi_task_t * task,stmf_data_buf_t * dbuf,uint32_t flags)39423fb517f7SJames Moore stmf_setup_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t flags)
39433fb517f7SJames Moore {
39443fb517f7SJames Moore stmf_i_scsi_task_t *itask =
39453fb517f7SJames Moore (stmf_i_scsi_task_t *)task->task_stmf_private;
39463fb517f7SJames Moore stmf_local_port_t *lport = task->task_lport;
39473fb517f7SJames Moore uint8_t ndx;
39483fb517f7SJames Moore stmf_status_t ret;
39493fb517f7SJames Moore
39503fb517f7SJames Moore ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
39513fb517f7SJames Moore ASSERT(lport->lport_ds->ds_setup_dbuf != NULL);
39523fb517f7SJames Moore ASSERT(dbuf->db_flags & DB_LU_DATA_BUF);
39533fb517f7SJames Moore
39543fb517f7SJames Moore if ((task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF) == 0)
39553fb517f7SJames Moore return (STMF_FAILURE);
39563fb517f7SJames Moore if (lport->lport_ds->ds_setup_dbuf == NULL)
39573fb517f7SJames Moore return (STMF_FAILURE);
39583fb517f7SJames Moore
39593fb517f7SJames Moore ndx = stmf_first_zero[itask->itask_allocated_buf_map];
39603fb517f7SJames Moore if (ndx == 0xff)
39613fb517f7SJames Moore return (STMF_FAILURE);
39623fb517f7SJames Moore ret = lport->lport_ds->ds_setup_dbuf(task, dbuf, flags);
39633fb517f7SJames Moore if (ret == STMF_FAILURE)
39643fb517f7SJames Moore return (STMF_FAILURE);
39653fb517f7SJames Moore itask->itask_dbufs[ndx] = dbuf;
39663fb517f7SJames Moore task->task_cur_nbufs++;
39673fb517f7SJames Moore itask->itask_allocated_buf_map |= (1 << ndx);
39683fb517f7SJames Moore dbuf->db_handle = ndx;
39693fb517f7SJames Moore
39703fb517f7SJames Moore return (STMF_SUCCESS);
39713fb517f7SJames Moore }
39723fb517f7SJames Moore
39733fb517f7SJames Moore void
stmf_teardown_dbuf(scsi_task_t * task,stmf_data_buf_t * dbuf)39743fb517f7SJames Moore stmf_teardown_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf)
39753fb517f7SJames Moore {
39763fb517f7SJames Moore stmf_i_scsi_task_t *itask =
39773fb517f7SJames Moore (stmf_i_scsi_task_t *)task->task_stmf_private;
39783fb517f7SJames Moore stmf_local_port_t *lport = task->task_lport;
39793fb517f7SJames Moore
39803fb517f7SJames Moore ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
39813fb517f7SJames Moore ASSERT(lport->lport_ds->ds_teardown_dbuf != NULL);
39823fb517f7SJames Moore ASSERT(dbuf->db_flags & DB_LU_DATA_BUF);
39833fb517f7SJames Moore
39843fb517f7SJames Moore itask->itask_allocated_buf_map &= ~(1 << dbuf->db_handle);
39853fb517f7SJames Moore task->task_cur_nbufs--;
39863fb517f7SJames Moore lport->lport_ds->ds_teardown_dbuf(lport->lport_ds, dbuf);
39873fb517f7SJames Moore }
39883fb517f7SJames Moore
3989fcf3ce44SJohn Forte void
stmf_free_dbuf(scsi_task_t * task,stmf_data_buf_t * dbuf)3990fcf3ce44SJohn Forte stmf_free_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf)
3991fcf3ce44SJohn Forte {
3992fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
3993fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
3994fcf3ce44SJohn Forte stmf_local_port_t *lport = task->task_lport;
3995fcf3ce44SJohn Forte
3996fcf3ce44SJohn Forte itask->itask_allocated_buf_map &= ~(1 << dbuf->db_handle);
3997fcf3ce44SJohn Forte task->task_cur_nbufs--;
3998fcf3ce44SJohn Forte lport->lport_ds->ds_free_data_buf(lport->lport_ds, dbuf);
3999fcf3ce44SJohn Forte }
4000fcf3ce44SJohn Forte
4001fcf3ce44SJohn Forte stmf_data_buf_t *
stmf_handle_to_buf(scsi_task_t * task,uint8_t h)4002fcf3ce44SJohn Forte stmf_handle_to_buf(scsi_task_t *task, uint8_t h)
4003fcf3ce44SJohn Forte {
4004fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask;
4005fcf3ce44SJohn Forte
4006fcf3ce44SJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
4007fcf3ce44SJohn Forte if (h > 3)
4008fcf3ce44SJohn Forte return (NULL);
4009fcf3ce44SJohn Forte return (itask->itask_dbufs[h]);
4010fcf3ce44SJohn Forte }
4011fcf3ce44SJohn Forte
4012fcf3ce44SJohn Forte /* ARGSUSED */
4013fcf3ce44SJohn 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)4014fcf3ce44SJohn Forte stmf_task_alloc(struct stmf_local_port *lport, stmf_scsi_session_t *ss,
4015fcf3ce44SJohn Forte uint8_t *lun, uint16_t cdb_length_in, uint16_t ext_id)
4016fcf3ce44SJohn Forte {
4017fcf3ce44SJohn Forte stmf_lu_t *lu;
4018fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
4019fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
4020fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask;
4021fcf3ce44SJohn Forte stmf_i_scsi_task_t **ppitask;
4022fcf3ce44SJohn Forte scsi_task_t *task;
4023fcf3ce44SJohn Forte uint8_t *l;
4024fcf3ce44SJohn Forte stmf_lun_map_ent_t *lun_map_ent;
4025fcf3ce44SJohn Forte uint16_t cdb_length;
4026fcf3ce44SJohn Forte uint16_t luNbr;
4027fcf3ce44SJohn Forte uint8_t new_task = 0;
4028fcf3ce44SJohn Forte
4029fcf3ce44SJohn Forte /*
4030fcf3ce44SJohn Forte * We allocate 7 extra bytes for CDB to provide a cdb pointer which
4031fcf3ce44SJohn Forte * is guaranteed to be 8 byte aligned. Some LU providers like OSD
4032fcf3ce44SJohn Forte * depend upon this alignment.
4033fcf3ce44SJohn Forte */
4034fcf3ce44SJohn Forte if (cdb_length_in >= 16)
4035fcf3ce44SJohn Forte cdb_length = cdb_length_in + 7;
4036fcf3ce44SJohn Forte else
4037fcf3ce44SJohn Forte cdb_length = 16 + 7;
4038fcf3ce44SJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4039fcf3ce44SJohn Forte luNbr = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4040fcf3ce44SJohn Forte rw_enter(iss->iss_lockp, RW_READER);
4041fcf3ce44SJohn Forte lun_map_ent =
4042fcf3ce44SJohn Forte (stmf_lun_map_ent_t *)stmf_get_ent_from_map(iss->iss_sm, luNbr);
4043fcf3ce44SJohn Forte if (!lun_map_ent) {
4044fcf3ce44SJohn Forte lu = dlun0;
4045fcf3ce44SJohn Forte } else {
4046fcf3ce44SJohn Forte lu = lun_map_ent->ent_lu;
4047fcf3ce44SJohn Forte }
4048fcf3ce44SJohn Forte ilu = lu->lu_stmf_private;
4049fcf3ce44SJohn Forte if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4050fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
4051fcf3ce44SJohn Forte return (NULL);
4052fcf3ce44SJohn Forte }
4053a49dc893SSaso Kiselkov ASSERT(lu == dlun0 || (ilu->ilu_state != STMF_STATE_OFFLINING &&
4054a49dc893SSaso Kiselkov ilu->ilu_state != STMF_STATE_OFFLINE));
4055fcf3ce44SJohn Forte do {
4056fcf3ce44SJohn Forte if (ilu->ilu_free_tasks == NULL) {
4057fcf3ce44SJohn Forte new_task = 1;
4058fcf3ce44SJohn Forte break;
4059fcf3ce44SJohn Forte }
4060fcf3ce44SJohn Forte mutex_enter(&ilu->ilu_task_lock);
4061fcf3ce44SJohn Forte for (ppitask = &ilu->ilu_free_tasks; (*ppitask != NULL) &&
4062fcf3ce44SJohn Forte ((*ppitask)->itask_cdb_buf_size < cdb_length);
40635679c89fSjv227347 ppitask = &((*ppitask)->itask_lu_free_next))
40645679c89fSjv227347 ;
4065fcf3ce44SJohn Forte if (*ppitask) {
4066fcf3ce44SJohn Forte itask = *ppitask;
4067fcf3ce44SJohn Forte *ppitask = (*ppitask)->itask_lu_free_next;
4068fcf3ce44SJohn Forte ilu->ilu_ntasks_free--;
4069fcf3ce44SJohn Forte if (ilu->ilu_ntasks_free < ilu->ilu_ntasks_min_free)
4070fcf3ce44SJohn Forte ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4071fcf3ce44SJohn Forte } else {
4072fcf3ce44SJohn Forte new_task = 1;
4073fcf3ce44SJohn Forte }
4074fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
4075fcf3ce44SJohn Forte /* CONSTCOND */
4076fcf3ce44SJohn Forte } while (0);
4077fcf3ce44SJohn Forte
4078fcf3ce44SJohn Forte if (!new_task) {
40793fb517f7SJames Moore /*
40803fb517f7SJames Moore * Save the task_cdb pointer and zero per cmd fields.
40813fb517f7SJames Moore * We know the task_cdb_length is large enough by task
40823fb517f7SJames Moore * selection process above.
40833fb517f7SJames Moore */
40843fb517f7SJames Moore uint8_t *save_cdb;
40853fb517f7SJames Moore uintptr_t t_start, t_end;
40863fb517f7SJames Moore
4087fcf3ce44SJohn Forte task = itask->itask_task;
40883fb517f7SJames Moore save_cdb = task->task_cdb; /* save */
40893fb517f7SJames Moore t_start = (uintptr_t)&task->task_flags;
40903fb517f7SJames Moore t_end = (uintptr_t)&task->task_extended_cmd;
40913fb517f7SJames Moore bzero((void *)t_start, (size_t)(t_end - t_start));
40923fb517f7SJames Moore task->task_cdb = save_cdb; /* restore */
4093fcf3ce44SJohn Forte itask->itask_ncmds = 0;
4094fcf3ce44SJohn Forte } else {
4095fcf3ce44SJohn Forte task = (scsi_task_t *)stmf_alloc(STMF_STRUCT_SCSI_TASK,
4096fcf3ce44SJohn Forte cdb_length, AF_FORCE_NOSLEEP);
4097fcf3ce44SJohn Forte if (task == NULL) {
4098fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
4099fcf3ce44SJohn Forte return (NULL);
4100fcf3ce44SJohn Forte }
4101fcf3ce44SJohn Forte task->task_lu = lu;
4102fcf3ce44SJohn Forte l = task->task_lun_no;
4103fcf3ce44SJohn Forte l[0] = lun[0];
4104fcf3ce44SJohn Forte l[1] = lun[1];
4105fcf3ce44SJohn Forte l[2] = lun[2];
4106fcf3ce44SJohn Forte l[3] = lun[3];
4107fcf3ce44SJohn Forte l[4] = lun[4];
4108fcf3ce44SJohn Forte l[5] = lun[5];
4109fcf3ce44SJohn Forte l[6] = lun[6];
4110fcf3ce44SJohn Forte l[7] = lun[7];
4111fcf3ce44SJohn Forte task->task_cdb = (uint8_t *)task->task_port_private;
4112fcf3ce44SJohn Forte if ((ulong_t)(task->task_cdb) & 7ul) {
4113fcf3ce44SJohn Forte task->task_cdb = (uint8_t *)(((ulong_t)
4114fcf3ce44SJohn Forte (task->task_cdb) + 7ul) & ~(7ul));
4115fcf3ce44SJohn Forte }
4116fcf3ce44SJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
4117fcf3ce44SJohn Forte itask->itask_cdb_buf_size = cdb_length;
411840c3e8ffSJohn Forte mutex_init(&itask->itask_audit_mutex, NULL, MUTEX_DRIVER, NULL);
4119fcf3ce44SJohn Forte }
4120fcf3ce44SJohn Forte task->task_session = ss;
4121fcf3ce44SJohn Forte task->task_lport = lport;
4122fcf3ce44SJohn Forte task->task_cdb_length = cdb_length_in;
4123fcf3ce44SJohn Forte itask->itask_flags = ITASK_IN_TRANSITION;
4124427fcaf8Stim szeto itask->itask_waitq_time = 0;
4125427fcaf8Stim szeto itask->itask_lu_read_time = itask->itask_lu_write_time = 0;
4126427fcaf8Stim szeto itask->itask_lport_read_time = itask->itask_lport_write_time = 0;
4127427fcaf8Stim szeto itask->itask_read_xfer = itask->itask_write_xfer = 0;
412840c3e8ffSJohn Forte itask->itask_audit_index = 0;
4129fcf3ce44SJohn Forte
4130fcf3ce44SJohn Forte if (new_task) {
4131fcf3ce44SJohn Forte if (lu->lu_task_alloc(task) != STMF_SUCCESS) {
4132fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
4133fcf3ce44SJohn Forte stmf_free(task);
4134fcf3ce44SJohn Forte return (NULL);
4135fcf3ce44SJohn Forte }
4136fcf3ce44SJohn Forte mutex_enter(&ilu->ilu_task_lock);
4137fcf3ce44SJohn Forte if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4138fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
4139fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
4140fcf3ce44SJohn Forte stmf_free(task);
4141fcf3ce44SJohn Forte return (NULL);
4142fcf3ce44SJohn Forte }
4143fcf3ce44SJohn Forte itask->itask_lu_next = ilu->ilu_tasks;
4144fcf3ce44SJohn Forte if (ilu->ilu_tasks)
4145fcf3ce44SJohn Forte ilu->ilu_tasks->itask_lu_prev = itask;
4146fcf3ce44SJohn Forte ilu->ilu_tasks = itask;
4147fcf3ce44SJohn Forte /* kmem_zalloc automatically makes itask->itask_lu_prev NULL */
4148fcf3ce44SJohn Forte ilu->ilu_ntasks++;
4149fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
4150fcf3ce44SJohn Forte }
4151fcf3ce44SJohn Forte
4152fcf3ce44SJohn Forte itask->itask_ilu_task_cntr = ilu->ilu_cur_task_cntr;
41531a5e258fSJosef 'Jeff' Sipek atomic_inc_32(itask->itask_ilu_task_cntr);
4154fcf3ce44SJohn Forte itask->itask_start_time = ddi_get_lbolt();
4155fcf3ce44SJohn Forte
4156fcf3ce44SJohn Forte if ((lun_map_ent != NULL) && ((itask->itask_itl_datap =
4157fcf3ce44SJohn Forte lun_map_ent->ent_itl_datap) != NULL)) {
41581a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&itask->itask_itl_datap->itl_counter);
4159fcf3ce44SJohn Forte task->task_lu_itl_handle = itask->itask_itl_datap->itl_handle;
4160fcf3ce44SJohn Forte } else {
4161fcf3ce44SJohn Forte itask->itask_itl_datap = NULL;
4162fcf3ce44SJohn Forte task->task_lu_itl_handle = NULL;
4163fcf3ce44SJohn Forte }
4164fcf3ce44SJohn Forte
4165fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
4166fcf3ce44SJohn Forte return (task);
4167fcf3ce44SJohn Forte }
4168fcf3ce44SJohn Forte
416945039663SJohn Forte static void
stmf_task_lu_free(scsi_task_t * task,stmf_i_scsi_session_t * iss)417045039663SJohn Forte stmf_task_lu_free(scsi_task_t *task, stmf_i_scsi_session_t *iss)
4171fcf3ce44SJohn Forte {
4172fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
4173fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
4174fcf3ce44SJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
4175fcf3ce44SJohn Forte
417645039663SJohn Forte ASSERT(rw_lock_held(iss->iss_lockp));
4177fcf3ce44SJohn Forte itask->itask_flags = ITASK_IN_FREE_LIST;
4178437be372SJohn Forte itask->itask_proxy_msg_id = 0;
4179fcf3ce44SJohn Forte mutex_enter(&ilu->ilu_task_lock);
4180fcf3ce44SJohn Forte itask->itask_lu_free_next = ilu->ilu_free_tasks;
4181fcf3ce44SJohn Forte ilu->ilu_free_tasks = itask;
4182fcf3ce44SJohn Forte ilu->ilu_ntasks_free++;
4183a49dc893SSaso Kiselkov if (ilu->ilu_ntasks == ilu->ilu_ntasks_free)
4184a49dc893SSaso Kiselkov cv_signal(&ilu->ilu_offline_pending_cv);
4185fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
41861a5e258fSJosef 'Jeff' Sipek atomic_dec_32(itask->itask_ilu_task_cntr);
4187fcf3ce44SJohn Forte }
4188fcf3ce44SJohn Forte
4189fcf3ce44SJohn Forte void
stmf_task_lu_check_freelist(stmf_i_lu_t * ilu)4190fcf3ce44SJohn Forte stmf_task_lu_check_freelist(stmf_i_lu_t *ilu)
4191fcf3ce44SJohn Forte {
4192fcf3ce44SJohn Forte uint32_t num_to_release, ndx;
4193fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask;
4194fcf3ce44SJohn Forte stmf_lu_t *lu = ilu->ilu_lu;
4195fcf3ce44SJohn Forte
4196fcf3ce44SJohn Forte ASSERT(ilu->ilu_ntasks_min_free <= ilu->ilu_ntasks_free);
4197fcf3ce44SJohn Forte
4198fcf3ce44SJohn Forte /* free half of the minimal free of the free tasks */
4199fcf3ce44SJohn Forte num_to_release = (ilu->ilu_ntasks_min_free + 1) / 2;
4200fcf3ce44SJohn Forte if (!num_to_release) {
4201fcf3ce44SJohn Forte return;
4202fcf3ce44SJohn Forte }
4203fcf3ce44SJohn Forte for (ndx = 0; ndx < num_to_release; ndx++) {
4204fcf3ce44SJohn Forte mutex_enter(&ilu->ilu_task_lock);
4205fcf3ce44SJohn Forte itask = ilu->ilu_free_tasks;
4206fcf3ce44SJohn Forte if (itask == NULL) {
4207fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
4208fcf3ce44SJohn Forte break;
4209fcf3ce44SJohn Forte }
4210fcf3ce44SJohn Forte ilu->ilu_free_tasks = itask->itask_lu_free_next;
4211fcf3ce44SJohn Forte ilu->ilu_ntasks_free--;
4212fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
4213fcf3ce44SJohn Forte
4214fcf3ce44SJohn Forte lu->lu_task_free(itask->itask_task);
4215fcf3ce44SJohn Forte mutex_enter(&ilu->ilu_task_lock);
4216fcf3ce44SJohn Forte if (itask->itask_lu_next)
4217fcf3ce44SJohn Forte itask->itask_lu_next->itask_lu_prev =
4218fcf3ce44SJohn Forte itask->itask_lu_prev;
4219fcf3ce44SJohn Forte if (itask->itask_lu_prev)
4220fcf3ce44SJohn Forte itask->itask_lu_prev->itask_lu_next =
4221fcf3ce44SJohn Forte itask->itask_lu_next;
4222fcf3ce44SJohn Forte else
4223fcf3ce44SJohn Forte ilu->ilu_tasks = itask->itask_lu_next;
4224fcf3ce44SJohn Forte
4225fcf3ce44SJohn Forte ilu->ilu_ntasks--;
4226fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
4227fcf3ce44SJohn Forte stmf_free(itask->itask_task);
4228fcf3ce44SJohn Forte }
4229fcf3ce44SJohn Forte }
4230fcf3ce44SJohn Forte
4231fcf3ce44SJohn Forte /*
4232fcf3ce44SJohn Forte * Called with stmf_lock held
4233fcf3ce44SJohn Forte */
4234fcf3ce44SJohn Forte void
stmf_check_freetask()4235fcf3ce44SJohn Forte stmf_check_freetask()
4236fcf3ce44SJohn Forte {
4237fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
4238fcf3ce44SJohn Forte clock_t endtime = ddi_get_lbolt() + drv_usectohz(10000);
4239fcf3ce44SJohn Forte
4240fcf3ce44SJohn Forte /* stmf_svc_ilu_draining may get changed after stmf_lock is released */
4241fcf3ce44SJohn Forte while ((ilu = stmf_state.stmf_svc_ilu_draining) != NULL) {
4242fcf3ce44SJohn Forte stmf_state.stmf_svc_ilu_draining = ilu->ilu_next;
4243fcf3ce44SJohn Forte if (!ilu->ilu_ntasks_min_free) {
4244fcf3ce44SJohn Forte ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4245fcf3ce44SJohn Forte continue;
4246fcf3ce44SJohn Forte }
4247fcf3ce44SJohn Forte ilu->ilu_flags |= ILU_STALL_DEREGISTER;
4248fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
4249fcf3ce44SJohn Forte stmf_task_lu_check_freelist(ilu);
4250fcf3ce44SJohn Forte /*
4251fcf3ce44SJohn Forte * we do not care about the accuracy of
4252fcf3ce44SJohn Forte * ilu_ntasks_min_free, so we don't lock here
4253fcf3ce44SJohn Forte */
4254fcf3ce44SJohn Forte ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4255fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
4256fcf3ce44SJohn Forte ilu->ilu_flags &= ~ILU_STALL_DEREGISTER;
4257fcf3ce44SJohn Forte cv_broadcast(&stmf_state.stmf_cv);
4258fcf3ce44SJohn Forte if (ddi_get_lbolt() >= endtime)
4259fcf3ce44SJohn Forte break;
4260fcf3ce44SJohn Forte }
4261fcf3ce44SJohn Forte }
4262fcf3ce44SJohn Forte
4263fcf3ce44SJohn Forte void
stmf_do_ilu_timeouts(stmf_i_lu_t * ilu)4264fcf3ce44SJohn Forte stmf_do_ilu_timeouts(stmf_i_lu_t *ilu)
4265fcf3ce44SJohn Forte {
4266fcf3ce44SJohn Forte clock_t l = ddi_get_lbolt();
4267fcf3ce44SJohn Forte clock_t ps = drv_usectohz(1000000);
4268fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask;
4269fcf3ce44SJohn Forte scsi_task_t *task;
4270fcf3ce44SJohn Forte uint32_t to;
4271fcf3ce44SJohn Forte
4272fcf3ce44SJohn Forte mutex_enter(&ilu->ilu_task_lock);
4273fcf3ce44SJohn Forte for (itask = ilu->ilu_tasks; itask != NULL;
4274fcf3ce44SJohn Forte itask = itask->itask_lu_next) {
4275fcf3ce44SJohn Forte if (itask->itask_flags & (ITASK_IN_FREE_LIST |
4276fcf3ce44SJohn Forte ITASK_BEING_ABORTED)) {
4277fcf3ce44SJohn Forte continue;
4278fcf3ce44SJohn Forte }
4279fcf3ce44SJohn Forte task = itask->itask_task;
4280fcf3ce44SJohn Forte if (task->task_timeout == 0)
4281fcf3ce44SJohn Forte to = stmf_default_task_timeout;
4282fcf3ce44SJohn Forte else
4283fcf3ce44SJohn Forte to = task->task_timeout;
4284fcf3ce44SJohn Forte if ((itask->itask_start_time + (to * ps)) > l)
4285fcf3ce44SJohn Forte continue;
4286fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
4287fcf3ce44SJohn Forte STMF_TIMEOUT, NULL);
4288fcf3ce44SJohn Forte }
4289fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
4290fcf3ce44SJohn Forte }
4291fcf3ce44SJohn Forte
4292fcf3ce44SJohn Forte /*
4293fcf3ce44SJohn Forte * Called with stmf_lock held
4294fcf3ce44SJohn Forte */
4295fcf3ce44SJohn Forte void
stmf_check_ilu_timing()4296fcf3ce44SJohn Forte stmf_check_ilu_timing()
4297fcf3ce44SJohn Forte {
4298fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
4299fcf3ce44SJohn Forte clock_t endtime = ddi_get_lbolt() + drv_usectohz(10000);
4300fcf3ce44SJohn Forte
4301fcf3ce44SJohn Forte /* stmf_svc_ilu_timing may get changed after stmf_lock is released */
4302fcf3ce44SJohn Forte while ((ilu = stmf_state.stmf_svc_ilu_timing) != NULL) {
4303fcf3ce44SJohn Forte stmf_state.stmf_svc_ilu_timing = ilu->ilu_next;
4304fcf3ce44SJohn Forte if (ilu->ilu_cur_task_cntr == (&ilu->ilu_task_cntr1)) {
4305fcf3ce44SJohn Forte if (ilu->ilu_task_cntr2 == 0) {
4306fcf3ce44SJohn Forte ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr2;
4307fcf3ce44SJohn Forte continue;
4308fcf3ce44SJohn Forte }
4309fcf3ce44SJohn Forte } else {
4310fcf3ce44SJohn Forte if (ilu->ilu_task_cntr1 == 0) {
4311fcf3ce44SJohn Forte ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
4312fcf3ce44SJohn Forte continue;
4313fcf3ce44SJohn Forte }
4314fcf3ce44SJohn Forte }
4315fcf3ce44SJohn Forte /*
4316fcf3ce44SJohn Forte * If we are here then it means that there is some slowdown
4317fcf3ce44SJohn Forte * in tasks on this lu. We need to check.
4318fcf3ce44SJohn Forte */
4319fcf3ce44SJohn Forte ilu->ilu_flags |= ILU_STALL_DEREGISTER;
4320fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
4321fcf3ce44SJohn Forte stmf_do_ilu_timeouts(ilu);
4322fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
4323fcf3ce44SJohn Forte ilu->ilu_flags &= ~ILU_STALL_DEREGISTER;
4324fcf3ce44SJohn Forte cv_broadcast(&stmf_state.stmf_cv);
4325fcf3ce44SJohn Forte if (ddi_get_lbolt() >= endtime)
4326fcf3ce44SJohn Forte break;
4327fcf3ce44SJohn Forte }
4328fcf3ce44SJohn Forte }
4329fcf3ce44SJohn Forte
4330fcf3ce44SJohn Forte /*
4331fcf3ce44SJohn Forte * Kills all tasks on a lu except tm_task
4332fcf3ce44SJohn Forte */
4333fcf3ce44SJohn Forte void
stmf_task_lu_killall(stmf_lu_t * lu,scsi_task_t * tm_task,stmf_status_t s)4334fcf3ce44SJohn Forte stmf_task_lu_killall(stmf_lu_t *lu, scsi_task_t *tm_task, stmf_status_t s)
4335fcf3ce44SJohn Forte {
4336fcf3ce44SJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4337fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask;
4338fcf3ce44SJohn Forte
4339fcf3ce44SJohn Forte mutex_enter(&ilu->ilu_task_lock);
4340fcf3ce44SJohn Forte
4341fcf3ce44SJohn Forte for (itask = ilu->ilu_tasks; itask != NULL;
4342fcf3ce44SJohn Forte itask = itask->itask_lu_next) {
4343fcf3ce44SJohn Forte if (itask->itask_flags & ITASK_IN_FREE_LIST)
4344fcf3ce44SJohn Forte continue;
4345fcf3ce44SJohn Forte if (itask->itask_task == tm_task)
4346fcf3ce44SJohn Forte continue;
4347fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, itask->itask_task, s, NULL);
4348fcf3ce44SJohn Forte }
4349fcf3ce44SJohn Forte mutex_exit(&ilu->ilu_task_lock);
4350fcf3ce44SJohn Forte }
4351fcf3ce44SJohn Forte
4352fcf3ce44SJohn Forte void
stmf_free_task_bufs(stmf_i_scsi_task_t * itask,stmf_local_port_t * lport)4353fcf3ce44SJohn Forte stmf_free_task_bufs(stmf_i_scsi_task_t *itask, stmf_local_port_t *lport)
4354fcf3ce44SJohn Forte {
4355fcf3ce44SJohn Forte int i;
4356fcf3ce44SJohn Forte uint8_t map;
4357fcf3ce44SJohn Forte
43583fb517f7SJames Moore if ((map = itask->itask_allocated_buf_map) == 0)
43593fb517f7SJames Moore return;
4360fcf3ce44SJohn Forte for (i = 0; i < 4; i++) {
4361fcf3ce44SJohn Forte if (map & 1) {
4362fcf3ce44SJohn Forte stmf_data_buf_t *dbuf;
4363fcf3ce44SJohn Forte
4364fcf3ce44SJohn Forte dbuf = itask->itask_dbufs[i];
43653fb517f7SJames Moore if (dbuf->db_xfer_start_timestamp) {
4366427fcaf8Stim szeto stmf_lport_xfer_done(itask, dbuf);
4367427fcaf8Stim szeto }
43683fb517f7SJames Moore if (dbuf->db_flags & DB_LU_DATA_BUF) {
43693fb517f7SJames Moore /*
43703fb517f7SJames Moore * LU needs to clean up buffer.
43713fb517f7SJames Moore * LU is required to free the buffer
43723fb517f7SJames Moore * in the xfer_done handler.
43733fb517f7SJames Moore */
43743fb517f7SJames Moore scsi_task_t *task = itask->itask_task;
43753fb517f7SJames Moore stmf_lu_t *lu = task->task_lu;
43763fb517f7SJames Moore
43773fb517f7SJames Moore lu->lu_dbuf_free(task, dbuf);
43783fb517f7SJames Moore ASSERT(((itask->itask_allocated_buf_map>>i)
43793fb517f7SJames Moore & 1) == 0); /* must be gone */
43803fb517f7SJames Moore } else {
43813fb517f7SJames Moore ASSERT(dbuf->db_lu_private == NULL);
43823fb517f7SJames Moore dbuf->db_lu_private = NULL;
4383fcf3ce44SJohn Forte lport->lport_ds->ds_free_data_buf(
4384fcf3ce44SJohn Forte lport->lport_ds, dbuf);
4385fcf3ce44SJohn Forte }
43863fb517f7SJames Moore }
4387fcf3ce44SJohn Forte map >>= 1;
4388fcf3ce44SJohn Forte }
4389fcf3ce44SJohn Forte itask->itask_allocated_buf_map = 0;
4390fcf3ce44SJohn Forte }
4391fcf3ce44SJohn Forte
4392fcf3ce44SJohn Forte void
stmf_task_free(scsi_task_t * task)4393fcf3ce44SJohn Forte stmf_task_free(scsi_task_t *task)
4394fcf3ce44SJohn Forte {
4395fcf3ce44SJohn Forte stmf_local_port_t *lport = task->task_lport;
4396fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
4397fcf3ce44SJohn Forte task->task_stmf_private;
439845039663SJohn Forte stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
439945039663SJohn Forte task->task_session->ss_stmf_private;
4400fcf3ce44SJohn Forte
440140c3e8ffSJohn Forte stmf_task_audit(itask, TE_TASK_FREE, CMD_OR_IOF_NA, NULL);
440240c3e8ffSJohn Forte
4403fcf3ce44SJohn Forte stmf_free_task_bufs(itask, lport);
4404427fcaf8Stim szeto stmf_itl_task_done(itask);
4405427fcaf8Stim szeto DTRACE_PROBE2(stmf__task__end, scsi_task_t *, task,
4406427fcaf8Stim szeto hrtime_t,
4407427fcaf8Stim szeto itask->itask_done_timestamp - itask->itask_start_timestamp);
4408fcf3ce44SJohn Forte if (itask->itask_itl_datap) {
44091a5e258fSJosef 'Jeff' Sipek if (atomic_dec_32_nv(&itask->itask_itl_datap->itl_counter) ==
44101a5e258fSJosef 'Jeff' Sipek 0) {
4411fcf3ce44SJohn Forte stmf_release_itl_handle(task->task_lu,
4412fcf3ce44SJohn Forte itask->itask_itl_datap);
4413fcf3ce44SJohn Forte }
4414fcf3ce44SJohn Forte }
441545039663SJohn Forte
441645039663SJohn Forte rw_enter(iss->iss_lockp, RW_READER);
4417fcf3ce44SJohn Forte lport->lport_task_free(task);
4418fcf3ce44SJohn Forte if (itask->itask_worker) {
44191a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&stmf_cur_ntasks);
44201a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&itask->itask_worker->worker_ref_count);
4421fcf3ce44SJohn Forte }
4422fcf3ce44SJohn Forte /*
4423fcf3ce44SJohn Forte * After calling stmf_task_lu_free, the task pointer can no longer
4424fcf3ce44SJohn Forte * be trusted.
4425fcf3ce44SJohn Forte */
442645039663SJohn Forte stmf_task_lu_free(task, iss);
442745039663SJohn Forte rw_exit(iss->iss_lockp);
4428fcf3ce44SJohn Forte }
4429fcf3ce44SJohn Forte
4430fcf3ce44SJohn Forte void
stmf_post_task(scsi_task_t * task,stmf_data_buf_t * dbuf)4431fcf3ce44SJohn Forte stmf_post_task(scsi_task_t *task, stmf_data_buf_t *dbuf)
4432fcf3ce44SJohn Forte {
4433fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
4434fcf3ce44SJohn Forte task->task_stmf_private;
4435fcf3ce44SJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
4436fcf3ce44SJohn Forte int nv;
4437fcf3ce44SJohn Forte uint32_t old, new;
4438fcf3ce44SJohn Forte uint32_t ct;
4439fcf3ce44SJohn Forte stmf_worker_t *w, *w1;
4440fcf3ce44SJohn Forte uint8_t tm;
4441fcf3ce44SJohn Forte
4442fcf3ce44SJohn Forte if (task->task_max_nbufs > 4)
4443fcf3ce44SJohn Forte task->task_max_nbufs = 4;
4444fcf3ce44SJohn Forte task->task_cur_nbufs = 0;
4445fcf3ce44SJohn Forte /* Latest value of currently running tasks */
44461a5e258fSJosef 'Jeff' Sipek ct = atomic_inc_32_nv(&stmf_cur_ntasks);
4447fcf3ce44SJohn Forte
4448fcf3ce44SJohn Forte /* Select the next worker using round robin */
44491a5e258fSJosef 'Jeff' Sipek nv = (int)atomic_inc_32_nv((uint32_t *)&stmf_worker_sel_counter);
4450fcf3ce44SJohn Forte if (nv >= stmf_nworkers_accepting_cmds) {
4451fcf3ce44SJohn Forte int s = nv;
4452fcf3ce44SJohn Forte do {
4453fcf3ce44SJohn Forte nv -= stmf_nworkers_accepting_cmds;
4454fcf3ce44SJohn Forte } while (nv >= stmf_nworkers_accepting_cmds);
4455fcf3ce44SJohn Forte if (nv < 0)
4456fcf3ce44SJohn Forte nv = 0;
4457fcf3ce44SJohn Forte /* Its ok if this cas fails */
4458fcf3ce44SJohn Forte (void) atomic_cas_32((uint32_t *)&stmf_worker_sel_counter,
4459fcf3ce44SJohn Forte s, nv);
4460fcf3ce44SJohn Forte }
4461fcf3ce44SJohn Forte w = &stmf_workers[nv];
4462fcf3ce44SJohn Forte
4463fcf3ce44SJohn Forte /*
4464fcf3ce44SJohn Forte * A worker can be pinned by interrupt. So select the next one
4465fcf3ce44SJohn Forte * if it has lower load.
4466fcf3ce44SJohn Forte */
4467fcf3ce44SJohn Forte if ((nv + 1) >= stmf_nworkers_accepting_cmds) {
4468fcf3ce44SJohn Forte w1 = stmf_workers;
4469fcf3ce44SJohn Forte } else {
4470fcf3ce44SJohn Forte w1 = &stmf_workers[nv + 1];
4471fcf3ce44SJohn Forte }
4472fcf3ce44SJohn Forte if (w1->worker_queue_depth < w->worker_queue_depth)
4473fcf3ce44SJohn Forte w = w1;
4474034d83c4Stim szeto
4475fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
4476fcf3ce44SJohn Forte if (((w->worker_flags & STMF_WORKER_STARTED) == 0) ||
4477fcf3ce44SJohn Forte (w->worker_flags & STMF_WORKER_TERMINATE)) {
4478fcf3ce44SJohn Forte /*
4479fcf3ce44SJohn Forte * Maybe we are in the middle of a change. Just go to
4480fcf3ce44SJohn Forte * the 1st worker.
4481fcf3ce44SJohn Forte */
4482fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4483fcf3ce44SJohn Forte w = stmf_workers;
4484fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
4485fcf3ce44SJohn Forte }
4486fcf3ce44SJohn Forte itask->itask_worker = w;
4487fcf3ce44SJohn Forte /*
4488fcf3ce44SJohn Forte * Track max system load inside the worker as we already have the
4489fcf3ce44SJohn Forte * worker lock (no point implementing another lock). The service
4490fcf3ce44SJohn Forte * thread will do the comparisons and figure out the max overall
4491fcf3ce44SJohn Forte * system load.
4492fcf3ce44SJohn Forte */
4493fcf3ce44SJohn Forte if (w->worker_max_sys_qdepth_pu < ct)
4494fcf3ce44SJohn Forte w->worker_max_sys_qdepth_pu = ct;
4495fcf3ce44SJohn Forte
4496fcf3ce44SJohn Forte do {
4497fcf3ce44SJohn Forte old = new = itask->itask_flags;
4498fcf3ce44SJohn Forte new |= ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE;
4499fcf3ce44SJohn Forte if (task->task_mgmt_function) {
4500fcf3ce44SJohn Forte tm = task->task_mgmt_function;
4501fcf3ce44SJohn Forte if ((tm == TM_TARGET_RESET) ||
4502fcf3ce44SJohn Forte (tm == TM_TARGET_COLD_RESET) ||
4503fcf3ce44SJohn Forte (tm == TM_TARGET_WARM_RESET)) {
4504fcf3ce44SJohn Forte new |= ITASK_DEFAULT_HANDLING;
4505fcf3ce44SJohn Forte }
4506fcf3ce44SJohn Forte } else if (task->task_cdb[0] == SCMD_REPORT_LUNS) {
4507fcf3ce44SJohn Forte new |= ITASK_DEFAULT_HANDLING;
4508fcf3ce44SJohn Forte }
4509fcf3ce44SJohn Forte new &= ~ITASK_IN_TRANSITION;
4510fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4511427fcaf8Stim szeto
4512427fcaf8Stim szeto stmf_itl_task_start(itask);
4513427fcaf8Stim szeto
4514fcf3ce44SJohn Forte itask->itask_worker_next = NULL;
4515fcf3ce44SJohn Forte if (w->worker_task_tail) {
4516fcf3ce44SJohn Forte w->worker_task_tail->itask_worker_next = itask;
4517fcf3ce44SJohn Forte } else {
4518fcf3ce44SJohn Forte w->worker_task_head = itask;
4519fcf3ce44SJohn Forte }
4520fcf3ce44SJohn Forte w->worker_task_tail = itask;
4521fcf3ce44SJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
4522fcf3ce44SJohn Forte w->worker_max_qdepth_pu = w->worker_queue_depth;
4523fcf3ce44SJohn Forte }
4524427fcaf8Stim szeto /* Measure task waitq time */
4525427fcaf8Stim szeto itask->itask_waitq_enter_timestamp = gethrtime();
45261a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&w->worker_ref_count);
4527fcf3ce44SJohn Forte itask->itask_cmd_stack[0] = ITASK_CMD_NEW_TASK;
4528fcf3ce44SJohn Forte itask->itask_ncmds = 1;
452940c3e8ffSJohn Forte stmf_task_audit(itask, TE_TASK_START, CMD_OR_IOF_NA, dbuf);
4530fcf3ce44SJohn Forte if (dbuf) {
4531fcf3ce44SJohn Forte itask->itask_allocated_buf_map = 1;
4532fcf3ce44SJohn Forte itask->itask_dbufs[0] = dbuf;
4533fcf3ce44SJohn Forte dbuf->db_handle = 0;
4534fcf3ce44SJohn Forte } else {
4535fcf3ce44SJohn Forte itask->itask_allocated_buf_map = 0;
4536fcf3ce44SJohn Forte itask->itask_dbufs[0] = NULL;
4537fcf3ce44SJohn Forte }
4538034d83c4Stim szeto
4539427fcaf8Stim szeto if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) {
4540427fcaf8Stim szeto w->worker_signal_timestamp = gethrtime();
4541427fcaf8Stim szeto DTRACE_PROBE2(worker__signal, stmf_worker_t *, w,
4542427fcaf8Stim szeto scsi_task_t *, task);
4543fcf3ce44SJohn Forte cv_signal(&w->worker_cv);
4544427fcaf8Stim szeto }
4545fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4546fcf3ce44SJohn Forte
4547fcf3ce44SJohn Forte /*
4548fcf3ce44SJohn Forte * This can only happen if during stmf_task_alloc(), ILU_RESET_ACTIVE
4549fcf3ce44SJohn Forte * was set between checking of ILU_RESET_ACTIVE and clearing of the
4550fcf3ce44SJohn Forte * ITASK_IN_FREE_LIST flag. Take care of these "sneaked-in" tasks here.
4551fcf3ce44SJohn Forte */
4552fcf3ce44SJohn Forte if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4553fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ABORTED, NULL);
4554fcf3ce44SJohn Forte }
4555fcf3ce44SJohn Forte }
4556fcf3ce44SJohn Forte
455740c3e8ffSJohn 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)455840c3e8ffSJohn Forte stmf_task_audit(stmf_i_scsi_task_t *itask,
455940c3e8ffSJohn Forte task_audit_event_t te, uint32_t cmd_or_iof, stmf_data_buf_t *dbuf)
456040c3e8ffSJohn Forte {
456140c3e8ffSJohn Forte stmf_task_audit_rec_t *ar;
456240c3e8ffSJohn Forte
456340c3e8ffSJohn Forte mutex_enter(&itask->itask_audit_mutex);
456440c3e8ffSJohn Forte ar = &itask->itask_audit_records[itask->itask_audit_index++];
456540c3e8ffSJohn Forte itask->itask_audit_index &= (ITASK_TASK_AUDIT_DEPTH - 1);
456640c3e8ffSJohn Forte ar->ta_event = te;
456740c3e8ffSJohn Forte ar->ta_cmd_or_iof = cmd_or_iof;
456840c3e8ffSJohn Forte ar->ta_itask_flags = itask->itask_flags;
456940c3e8ffSJohn Forte ar->ta_dbuf = dbuf;
457040c3e8ffSJohn Forte gethrestime(&ar->ta_timestamp);
457140c3e8ffSJohn Forte mutex_exit(&itask->itask_audit_mutex);
457240c3e8ffSJohn Forte }
457340c3e8ffSJohn Forte
457440c3e8ffSJohn Forte
4575fcf3ce44SJohn Forte /*
4576fcf3ce44SJohn Forte * ++++++++++++++ ABORT LOGIC ++++++++++++++++++++
4577fcf3ce44SJohn Forte * Once ITASK_BEING_ABORTED is set, ITASK_KNOWN_TO_LU can be reset already
4578fcf3ce44SJohn Forte * i.e. before ITASK_BEING_ABORTED being set. But if it was not, it cannot
4579fcf3ce44SJohn Forte * be reset until the LU explicitly calls stmf_task_lu_aborted(). Of course
4580fcf3ce44SJohn Forte * the LU will make this call only if we call the LU's abort entry point.
4581fcf3ce44SJohn Forte * we will only call that entry point if ITASK_KNOWN_TO_LU was set.
4582fcf3ce44SJohn Forte *
4583fcf3ce44SJohn Forte * Same logic applies for the port.
4584fcf3ce44SJohn Forte *
4585fcf3ce44SJohn Forte * Also ITASK_BEING_ABORTED will not be allowed to set if both KNOWN_TO_LU
4586fcf3ce44SJohn Forte * and KNOWN_TO_TGT_PORT are reset.
4587fcf3ce44SJohn Forte *
4588fcf3ce44SJohn Forte * +++++++++++++++++++++++++++++++++++++++++++++++
4589fcf3ce44SJohn Forte */
4590fcf3ce44SJohn Forte
4591fcf3ce44SJohn Forte stmf_status_t
stmf_xfer_data(scsi_task_t * task,stmf_data_buf_t * dbuf,uint32_t ioflags)4592fcf3ce44SJohn Forte stmf_xfer_data(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t ioflags)
4593fcf3ce44SJohn Forte {
459440c3e8ffSJohn Forte stmf_status_t ret = STMF_SUCCESS;
4595e17f3b22Stim szeto
4596fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
4597fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
4598fcf3ce44SJohn Forte
459940c3e8ffSJohn Forte stmf_task_audit(itask, TE_XFER_START, ioflags, dbuf);
460040c3e8ffSJohn Forte
4601fcf3ce44SJohn Forte if (ioflags & STMF_IOF_LU_DONE) {
4602fcf3ce44SJohn Forte uint32_t new, old;
4603fcf3ce44SJohn Forte do {
4604fcf3ce44SJohn Forte new = old = itask->itask_flags;
4605fcf3ce44SJohn Forte if (new & ITASK_BEING_ABORTED)
4606fcf3ce44SJohn Forte return (STMF_ABORTED);
4607fcf3ce44SJohn Forte new &= ~ITASK_KNOWN_TO_LU;
4608fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4609fcf3ce44SJohn Forte }
4610fcf3ce44SJohn Forte if (itask->itask_flags & ITASK_BEING_ABORTED)
4611fcf3ce44SJohn Forte return (STMF_ABORTED);
4612fcf3ce44SJohn Forte #ifdef DEBUG
4613427fcaf8Stim szeto if (!(ioflags & STMF_IOF_STATS_ONLY) && stmf_drop_buf_counter > 0) {
4614*9c68c052SJosef 'Jeff' Sipek if (atomic_dec_32_nv(&stmf_drop_buf_counter) == 1)
4615fcf3ce44SJohn Forte return (STMF_SUCCESS);
4616fcf3ce44SJohn Forte }
4617fcf3ce44SJohn Forte #endif
4618034d83c4Stim szeto
4619034d83c4Stim szeto stmf_update_kstat_lu_io(task, dbuf);
4620034d83c4Stim szeto stmf_update_kstat_lport_io(task, dbuf);
4621427fcaf8Stim szeto stmf_lport_xfer_start(itask, dbuf);
4622427fcaf8Stim szeto if (ioflags & STMF_IOF_STATS_ONLY) {
4623427fcaf8Stim szeto stmf_lport_xfer_done(itask, dbuf);
4624427fcaf8Stim szeto return (STMF_SUCCESS);
4625427fcaf8Stim szeto }
4626034d83c4Stim szeto
462740c3e8ffSJohn Forte dbuf->db_flags |= DB_LPORT_XFER_ACTIVE;
4628e17f3b22Stim szeto ret = task->task_lport->lport_xfer_data(task, dbuf, ioflags);
4629427fcaf8Stim szeto
4630427fcaf8Stim szeto /*
4631427fcaf8Stim szeto * Port provider may have already called the buffer callback in
4632427fcaf8Stim szeto * which case dbuf->db_xfer_start_timestamp will be 0.
4633427fcaf8Stim szeto */
463440c3e8ffSJohn Forte if (ret != STMF_SUCCESS) {
463540c3e8ffSJohn Forte dbuf->db_flags &= ~DB_LPORT_XFER_ACTIVE;
463640c3e8ffSJohn Forte if (dbuf->db_xfer_start_timestamp != 0)
4637427fcaf8Stim szeto stmf_lport_xfer_done(itask, dbuf);
4638427fcaf8Stim szeto }
4639427fcaf8Stim szeto
4640e17f3b22Stim szeto return (ret);
4641fcf3ce44SJohn Forte }
4642fcf3ce44SJohn Forte
4643fcf3ce44SJohn Forte void
stmf_data_xfer_done(scsi_task_t * task,stmf_data_buf_t * dbuf,uint32_t iof)4644fcf3ce44SJohn Forte stmf_data_xfer_done(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t iof)
4645fcf3ce44SJohn Forte {
4646fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
4647fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
464840c3e8ffSJohn Forte stmf_i_local_port_t *ilport;
4649fcf3ce44SJohn Forte stmf_worker_t *w = itask->itask_worker;
4650fcf3ce44SJohn Forte uint32_t new, old;
4651427fcaf8Stim szeto uint8_t update_queue_flags, free_it, queue_it;
4652427fcaf8Stim szeto
4653427fcaf8Stim szeto stmf_lport_xfer_done(itask, dbuf);
4654fcf3ce44SJohn Forte
465540c3e8ffSJohn Forte stmf_task_audit(itask, TE_XFER_DONE, iof, dbuf);
465640c3e8ffSJohn Forte
465740c3e8ffSJohn Forte /* Guard against unexpected completions from the lport */
465840c3e8ffSJohn Forte if (dbuf->db_flags & DB_LPORT_XFER_ACTIVE) {
465940c3e8ffSJohn Forte dbuf->db_flags &= ~DB_LPORT_XFER_ACTIVE;
466040c3e8ffSJohn Forte } else {
466140c3e8ffSJohn Forte /*
466240c3e8ffSJohn Forte * This should never happen.
466340c3e8ffSJohn Forte */
466440c3e8ffSJohn Forte ilport = task->task_lport->lport_stmf_private;
466540c3e8ffSJohn Forte ilport->ilport_unexpected_comp++;
466640c3e8ffSJohn Forte cmn_err(CE_PANIC, "Unexpected xfer completion task %p dbuf %p",
466740c3e8ffSJohn Forte (void *)task, (void *)dbuf);
466840c3e8ffSJohn Forte return;
466940c3e8ffSJohn Forte }
467040c3e8ffSJohn Forte
4671fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
4672fcf3ce44SJohn Forte do {
4673fcf3ce44SJohn Forte new = old = itask->itask_flags;
4674fcf3ce44SJohn Forte if (old & ITASK_BEING_ABORTED) {
4675fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4676fcf3ce44SJohn Forte return;
4677fcf3ce44SJohn Forte }
4678fcf3ce44SJohn Forte free_it = 0;
4679fcf3ce44SJohn Forte if (iof & STMF_IOF_LPORT_DONE) {
4680fcf3ce44SJohn Forte new &= ~ITASK_KNOWN_TO_TGT_PORT;
4681fcf3ce44SJohn Forte task->task_completion_status = dbuf->db_xfer_status;
4682fcf3ce44SJohn Forte free_it = 1;
4683fcf3ce44SJohn Forte }
4684fcf3ce44SJohn Forte /*
4685fcf3ce44SJohn Forte * If the task is known to LU then queue it. But if
4686fcf3ce44SJohn Forte * it is already queued (multiple completions) then
4687fcf3ce44SJohn Forte * just update the buffer information by grabbing the
4688fcf3ce44SJohn Forte * worker lock. If the task is not known to LU,
4689fcf3ce44SJohn Forte * completed/aborted, then see if we need to
4690fcf3ce44SJohn Forte * free this task.
4691fcf3ce44SJohn Forte */
4692fcf3ce44SJohn Forte if (old & ITASK_KNOWN_TO_LU) {
4693fcf3ce44SJohn Forte free_it = 0;
4694fcf3ce44SJohn Forte update_queue_flags = 1;
4695fcf3ce44SJohn Forte if (old & ITASK_IN_WORKER_QUEUE) {
4696fcf3ce44SJohn Forte queue_it = 0;
4697fcf3ce44SJohn Forte } else {
4698fcf3ce44SJohn Forte queue_it = 1;
4699fcf3ce44SJohn Forte new |= ITASK_IN_WORKER_QUEUE;
4700fcf3ce44SJohn Forte }
4701fcf3ce44SJohn Forte } else {
4702fcf3ce44SJohn Forte update_queue_flags = 0;
4703fcf3ce44SJohn Forte queue_it = 0;
4704fcf3ce44SJohn Forte }
4705fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4706fcf3ce44SJohn Forte
4707fcf3ce44SJohn Forte if (update_queue_flags) {
4708fcf3ce44SJohn Forte uint8_t cmd = (dbuf->db_handle << 5) | ITASK_CMD_DATA_XFER_DONE;
4709fcf3ce44SJohn Forte
4710fcf3ce44SJohn Forte ASSERT(itask->itask_ncmds < ITASK_MAX_NCMDS);
4711fcf3ce44SJohn Forte itask->itask_cmd_stack[itask->itask_ncmds++] = cmd;
4712fcf3ce44SJohn Forte if (queue_it) {
4713fcf3ce44SJohn Forte itask->itask_worker_next = NULL;
4714fcf3ce44SJohn Forte if (w->worker_task_tail) {
4715fcf3ce44SJohn Forte w->worker_task_tail->itask_worker_next = itask;
4716fcf3ce44SJohn Forte } else {
4717fcf3ce44SJohn Forte w->worker_task_head = itask;
4718fcf3ce44SJohn Forte }
4719fcf3ce44SJohn Forte w->worker_task_tail = itask;
4720427fcaf8Stim szeto /* Measure task waitq time */
4721427fcaf8Stim szeto itask->itask_waitq_enter_timestamp = gethrtime();
4722fcf3ce44SJohn Forte if (++(w->worker_queue_depth) >
4723fcf3ce44SJohn Forte w->worker_max_qdepth_pu) {
4724fcf3ce44SJohn Forte w->worker_max_qdepth_pu = w->worker_queue_depth;
4725fcf3ce44SJohn Forte }
4726fcf3ce44SJohn Forte if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
4727fcf3ce44SJohn Forte cv_signal(&w->worker_cv);
4728fcf3ce44SJohn Forte }
4729fcf3ce44SJohn Forte }
4730fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4731fcf3ce44SJohn Forte
4732fcf3ce44SJohn Forte if (free_it) {
4733fcf3ce44SJohn Forte if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
4734fcf3ce44SJohn Forte ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
4735fcf3ce44SJohn Forte ITASK_BEING_ABORTED)) == 0) {
4736fcf3ce44SJohn Forte stmf_task_free(task);
4737fcf3ce44SJohn Forte }
4738fcf3ce44SJohn Forte }
4739fcf3ce44SJohn Forte }
4740fcf3ce44SJohn Forte
4741fcf3ce44SJohn Forte stmf_status_t
stmf_send_scsi_status(scsi_task_t * task,uint32_t ioflags)4742fcf3ce44SJohn Forte stmf_send_scsi_status(scsi_task_t *task, uint32_t ioflags)
4743fcf3ce44SJohn Forte {
4744e17f3b22Stim szeto DTRACE_PROBE1(scsi__send__status, scsi_task_t *, task);
4745e17f3b22Stim szeto
4746fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
4747fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
474840c3e8ffSJohn Forte
474940c3e8ffSJohn Forte stmf_task_audit(itask, TE_SEND_STATUS, ioflags, NULL);
475040c3e8ffSJohn Forte
4751fcf3ce44SJohn Forte if (ioflags & STMF_IOF_LU_DONE) {
4752fcf3ce44SJohn Forte uint32_t new, old;
4753fcf3ce44SJohn Forte do {
4754fcf3ce44SJohn Forte new = old = itask->itask_flags;
4755fcf3ce44SJohn Forte if (new & ITASK_BEING_ABORTED)
4756fcf3ce44SJohn Forte return (STMF_ABORTED);
4757fcf3ce44SJohn Forte new &= ~ITASK_KNOWN_TO_LU;
4758fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4759fcf3ce44SJohn Forte }
4760fcf3ce44SJohn Forte
4761fcf3ce44SJohn Forte if (!(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT)) {
4762fcf3ce44SJohn Forte return (STMF_SUCCESS);
4763fcf3ce44SJohn Forte }
4764fcf3ce44SJohn Forte
4765fcf3ce44SJohn Forte if (itask->itask_flags & ITASK_BEING_ABORTED)
4766fcf3ce44SJohn Forte return (STMF_ABORTED);
4767fcf3ce44SJohn Forte
4768fcf3ce44SJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
4769fcf3ce44SJohn Forte task->task_status_ctrl = 0;
4770fcf3ce44SJohn Forte task->task_resid = 0;
4771fcf3ce44SJohn Forte } else if (task->task_cmd_xfer_length >
4772fcf3ce44SJohn Forte task->task_expected_xfer_length) {
4773fcf3ce44SJohn Forte task->task_status_ctrl = TASK_SCTRL_OVER;
4774fcf3ce44SJohn Forte task->task_resid = task->task_cmd_xfer_length -
4775fcf3ce44SJohn Forte task->task_expected_xfer_length;
4776fcf3ce44SJohn Forte } else if (task->task_nbytes_transferred <
4777fcf3ce44SJohn Forte task->task_expected_xfer_length) {
4778fcf3ce44SJohn Forte task->task_status_ctrl = TASK_SCTRL_UNDER;
4779fcf3ce44SJohn Forte task->task_resid = task->task_expected_xfer_length -
4780fcf3ce44SJohn Forte task->task_nbytes_transferred;
4781fcf3ce44SJohn Forte } else {
4782fcf3ce44SJohn Forte task->task_status_ctrl = 0;
4783fcf3ce44SJohn Forte task->task_resid = 0;
4784fcf3ce44SJohn Forte }
4785fcf3ce44SJohn Forte return (task->task_lport->lport_send_status(task, ioflags));
4786fcf3ce44SJohn Forte }
4787fcf3ce44SJohn Forte
4788fcf3ce44SJohn Forte void
stmf_send_status_done(scsi_task_t * task,stmf_status_t s,uint32_t iof)4789fcf3ce44SJohn Forte stmf_send_status_done(scsi_task_t *task, stmf_status_t s, uint32_t iof)
4790fcf3ce44SJohn Forte {
4791fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
4792fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
4793fcf3ce44SJohn Forte stmf_worker_t *w = itask->itask_worker;
4794fcf3ce44SJohn Forte uint32_t new, old;
4795427fcaf8Stim szeto uint8_t free_it, queue_it;
4796fcf3ce44SJohn Forte
479740c3e8ffSJohn Forte stmf_task_audit(itask, TE_SEND_STATUS_DONE, iof, NULL);
479840c3e8ffSJohn Forte
4799fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
4800fcf3ce44SJohn Forte do {
4801fcf3ce44SJohn Forte new = old = itask->itask_flags;
4802fcf3ce44SJohn Forte if (old & ITASK_BEING_ABORTED) {
4803fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4804fcf3ce44SJohn Forte return;
4805fcf3ce44SJohn Forte }
4806fcf3ce44SJohn Forte free_it = 0;
4807fcf3ce44SJohn Forte if (iof & STMF_IOF_LPORT_DONE) {
4808fcf3ce44SJohn Forte new &= ~ITASK_KNOWN_TO_TGT_PORT;
4809fcf3ce44SJohn Forte free_it = 1;
4810fcf3ce44SJohn Forte }
4811fcf3ce44SJohn Forte /*
4812fcf3ce44SJohn Forte * If the task is known to LU then queue it. But if
4813fcf3ce44SJohn Forte * it is already queued (multiple completions) then
4814fcf3ce44SJohn Forte * just update the buffer information by grabbing the
4815fcf3ce44SJohn Forte * worker lock. If the task is not known to LU,
4816fcf3ce44SJohn Forte * completed/aborted, then see if we need to
4817fcf3ce44SJohn Forte * free this task.
4818fcf3ce44SJohn Forte */
4819fcf3ce44SJohn Forte if (old & ITASK_KNOWN_TO_LU) {
4820fcf3ce44SJohn Forte free_it = 0;
4821fcf3ce44SJohn Forte queue_it = 1;
4822fcf3ce44SJohn Forte if (old & ITASK_IN_WORKER_QUEUE) {
4823fcf3ce44SJohn Forte cmn_err(CE_PANIC, "status completion received"
4824fcf3ce44SJohn Forte " when task is already in worker queue "
4825fcf3ce44SJohn Forte " task = %p", (void *)task);
4826fcf3ce44SJohn Forte }
4827fcf3ce44SJohn Forte new |= ITASK_IN_WORKER_QUEUE;
4828fcf3ce44SJohn Forte } else {
4829fcf3ce44SJohn Forte queue_it = 0;
4830fcf3ce44SJohn Forte }
4831fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4832fcf3ce44SJohn Forte task->task_completion_status = s;
4833fcf3ce44SJohn Forte
4834034d83c4Stim szeto
4835fcf3ce44SJohn Forte if (queue_it) {
4836fcf3ce44SJohn Forte ASSERT(itask->itask_ncmds < ITASK_MAX_NCMDS);
4837fcf3ce44SJohn Forte itask->itask_cmd_stack[itask->itask_ncmds++] =
4838fcf3ce44SJohn Forte ITASK_CMD_STATUS_DONE;
4839fcf3ce44SJohn Forte itask->itask_worker_next = NULL;
4840fcf3ce44SJohn Forte if (w->worker_task_tail) {
4841fcf3ce44SJohn Forte w->worker_task_tail->itask_worker_next = itask;
4842fcf3ce44SJohn Forte } else {
4843fcf3ce44SJohn Forte w->worker_task_head = itask;
4844fcf3ce44SJohn Forte }
4845fcf3ce44SJohn Forte w->worker_task_tail = itask;
4846427fcaf8Stim szeto /* Measure task waitq time */
4847427fcaf8Stim szeto itask->itask_waitq_enter_timestamp = gethrtime();
4848fcf3ce44SJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
4849fcf3ce44SJohn Forte w->worker_max_qdepth_pu = w->worker_queue_depth;
4850fcf3ce44SJohn Forte }
4851fcf3ce44SJohn Forte if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
4852fcf3ce44SJohn Forte cv_signal(&w->worker_cv);
4853fcf3ce44SJohn Forte }
4854fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4855fcf3ce44SJohn Forte
4856fcf3ce44SJohn Forte if (free_it) {
4857fcf3ce44SJohn Forte if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
4858fcf3ce44SJohn Forte ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
4859fcf3ce44SJohn Forte ITASK_BEING_ABORTED)) == 0) {
4860fcf3ce44SJohn Forte stmf_task_free(task);
4861fcf3ce44SJohn Forte } else {
4862fcf3ce44SJohn Forte cmn_err(CE_PANIC, "LU is done with the task but LPORT "
4863437be372SJohn Forte " is not done, itask %p itask_flags %x",
4864437be372SJohn Forte (void *)itask, itask->itask_flags);
4865fcf3ce44SJohn Forte }
4866fcf3ce44SJohn Forte }
4867fcf3ce44SJohn Forte }
4868fcf3ce44SJohn Forte
4869fcf3ce44SJohn Forte void
stmf_task_lu_done(scsi_task_t * task)4870fcf3ce44SJohn Forte stmf_task_lu_done(scsi_task_t *task)
4871fcf3ce44SJohn Forte {
4872fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
4873fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
4874fcf3ce44SJohn Forte stmf_worker_t *w = itask->itask_worker;
4875fcf3ce44SJohn Forte uint32_t new, old;
4876fcf3ce44SJohn Forte
4877fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
4878fcf3ce44SJohn Forte do {
4879fcf3ce44SJohn Forte new = old = itask->itask_flags;
4880fcf3ce44SJohn Forte if (old & ITASK_BEING_ABORTED) {
4881fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4882fcf3ce44SJohn Forte return;
4883fcf3ce44SJohn Forte }
4884fcf3ce44SJohn Forte if (old & ITASK_IN_WORKER_QUEUE) {
4885fcf3ce44SJohn Forte cmn_err(CE_PANIC, "task_lu_done received"
4886fcf3ce44SJohn Forte " when task is in worker queue "
4887fcf3ce44SJohn Forte " task = %p", (void *)task);
4888fcf3ce44SJohn Forte }
4889fcf3ce44SJohn Forte new &= ~ITASK_KNOWN_TO_LU;
4890fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4891fcf3ce44SJohn Forte
4892fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4893fcf3ce44SJohn Forte
4894fcf3ce44SJohn Forte if ((itask->itask_flags & (ITASK_KNOWN_TO_LU |
4895fcf3ce44SJohn Forte ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
4896fcf3ce44SJohn Forte ITASK_BEING_ABORTED)) == 0) {
4897fcf3ce44SJohn Forte stmf_task_free(task);
4898fcf3ce44SJohn Forte } else {
4899fcf3ce44SJohn Forte cmn_err(CE_PANIC, "stmf_lu_done should be the last stage but "
4900fcf3ce44SJohn Forte " the task is still not done, task = %p", (void *)task);
4901fcf3ce44SJohn Forte }
4902fcf3ce44SJohn Forte }
4903fcf3ce44SJohn Forte
4904fcf3ce44SJohn Forte void
stmf_queue_task_for_abort(scsi_task_t * task,stmf_status_t s)4905fcf3ce44SJohn Forte stmf_queue_task_for_abort(scsi_task_t *task, stmf_status_t s)
4906fcf3ce44SJohn Forte {
4907fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
4908fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
4909fcf3ce44SJohn Forte stmf_worker_t *w;
4910fcf3ce44SJohn Forte uint32_t old, new;
4911fcf3ce44SJohn Forte
491240c3e8ffSJohn Forte stmf_task_audit(itask, TE_TASK_ABORT, CMD_OR_IOF_NA, NULL);
491340c3e8ffSJohn Forte
4914fcf3ce44SJohn Forte do {
4915fcf3ce44SJohn Forte old = new = itask->itask_flags;
4916fcf3ce44SJohn Forte if ((old & ITASK_BEING_ABORTED) ||
4917fcf3ce44SJohn Forte ((old & (ITASK_KNOWN_TO_TGT_PORT |
4918fcf3ce44SJohn Forte ITASK_KNOWN_TO_LU)) == 0)) {
4919fcf3ce44SJohn Forte return;
4920fcf3ce44SJohn Forte }
4921fcf3ce44SJohn Forte new |= ITASK_BEING_ABORTED;
4922fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4923fcf3ce44SJohn Forte task->task_completion_status = s;
4924fcf3ce44SJohn Forte itask->itask_start_time = ddi_get_lbolt();
4925fcf3ce44SJohn Forte
4926fcf3ce44SJohn Forte if (((w = itask->itask_worker) == NULL) ||
4927fcf3ce44SJohn Forte (itask->itask_flags & ITASK_IN_TRANSITION)) {
4928fcf3ce44SJohn Forte return;
4929fcf3ce44SJohn Forte }
4930fcf3ce44SJohn Forte
4931fcf3ce44SJohn Forte /* Queue it and get out */
4932fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
4933fcf3ce44SJohn Forte if (itask->itask_flags & ITASK_IN_WORKER_QUEUE) {
4934fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4935fcf3ce44SJohn Forte return;
4936fcf3ce44SJohn Forte }
4937fcf3ce44SJohn Forte atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE);
4938fcf3ce44SJohn Forte itask->itask_worker_next = NULL;
4939fcf3ce44SJohn Forte if (w->worker_task_tail) {
4940fcf3ce44SJohn Forte w->worker_task_tail->itask_worker_next = itask;
4941fcf3ce44SJohn Forte } else {
4942fcf3ce44SJohn Forte w->worker_task_head = itask;
4943fcf3ce44SJohn Forte }
4944fcf3ce44SJohn Forte w->worker_task_tail = itask;
4945fcf3ce44SJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
4946fcf3ce44SJohn Forte w->worker_max_qdepth_pu = w->worker_queue_depth;
4947fcf3ce44SJohn Forte }
4948fcf3ce44SJohn Forte if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
4949fcf3ce44SJohn Forte cv_signal(&w->worker_cv);
4950fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
4951fcf3ce44SJohn Forte }
4952fcf3ce44SJohn Forte
4953fcf3ce44SJohn Forte void
stmf_abort(int abort_cmd,scsi_task_t * task,stmf_status_t s,void * arg)4954fcf3ce44SJohn Forte stmf_abort(int abort_cmd, scsi_task_t *task, stmf_status_t s, void *arg)
4955fcf3ce44SJohn Forte {
4956fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask = NULL;
4957fcf3ce44SJohn Forte uint32_t old, new, f, rf;
4958fcf3ce44SJohn Forte
4959e17f3b22Stim szeto DTRACE_PROBE2(scsi__task__abort, scsi_task_t *, task,
4960e17f3b22Stim szeto stmf_status_t, s);
4961e17f3b22Stim szeto
4962fcf3ce44SJohn Forte switch (abort_cmd) {
4963fcf3ce44SJohn Forte case STMF_QUEUE_ABORT_LU:
4964fcf3ce44SJohn Forte stmf_task_lu_killall((stmf_lu_t *)arg, task, s);
4965fcf3ce44SJohn Forte return;
4966fcf3ce44SJohn Forte case STMF_QUEUE_TASK_ABORT:
4967fcf3ce44SJohn Forte stmf_queue_task_for_abort(task, s);
4968fcf3ce44SJohn Forte return;
4969fcf3ce44SJohn Forte case STMF_REQUEUE_TASK_ABORT_LPORT:
4970fcf3ce44SJohn Forte rf = ITASK_TGT_PORT_ABORT_CALLED;
4971fcf3ce44SJohn Forte f = ITASK_KNOWN_TO_TGT_PORT;
4972fcf3ce44SJohn Forte break;
4973fcf3ce44SJohn Forte case STMF_REQUEUE_TASK_ABORT_LU:
4974fcf3ce44SJohn Forte rf = ITASK_LU_ABORT_CALLED;
4975fcf3ce44SJohn Forte f = ITASK_KNOWN_TO_LU;
4976fcf3ce44SJohn Forte break;
4977fcf3ce44SJohn Forte default:
4978fcf3ce44SJohn Forte return;
4979fcf3ce44SJohn Forte }
4980fcf3ce44SJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
4981fcf3ce44SJohn Forte f |= ITASK_BEING_ABORTED | rf;
4982fcf3ce44SJohn Forte do {
4983fcf3ce44SJohn Forte old = new = itask->itask_flags;
4984fcf3ce44SJohn Forte if ((old & f) != f) {
4985fcf3ce44SJohn Forte return;
4986fcf3ce44SJohn Forte }
4987fcf3ce44SJohn Forte new &= ~rf;
4988fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
4989fcf3ce44SJohn Forte }
4990fcf3ce44SJohn Forte
4991fcf3ce44SJohn Forte void
stmf_task_lu_aborted(scsi_task_t * task,stmf_status_t s,uint32_t iof)4992fcf3ce44SJohn Forte stmf_task_lu_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof)
4993fcf3ce44SJohn Forte {
4994fcf3ce44SJohn Forte char info[STMF_CHANGE_INFO_LEN];
4995fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask = TASK_TO_ITASK(task);
4996fcf3ce44SJohn Forte unsigned long long st;
4997fcf3ce44SJohn Forte
499840c3e8ffSJohn Forte stmf_task_audit(itask, TE_TASK_LU_ABORTED, iof, NULL);
499940c3e8ffSJohn Forte
5000fcf3ce44SJohn Forte st = s; /* gcc fix */
5001fcf3ce44SJohn Forte if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) {
50024558d122SViswanathan Kannappan (void) snprintf(info, sizeof (info),
5003fcf3ce44SJohn Forte "task %p, lu failed to abort ret=%llx", (void *)task, st);
5004fcf3ce44SJohn Forte } else if ((iof & STMF_IOF_LU_DONE) == 0) {
50054558d122SViswanathan Kannappan (void) snprintf(info, sizeof (info),
5006fcf3ce44SJohn Forte "Task aborted but LU is not finished, task ="
5007fcf3ce44SJohn Forte "%p, s=%llx, iof=%x", (void *)task, st, iof);
5008fcf3ce44SJohn Forte } else {
5009fcf3ce44SJohn Forte /*
5010fcf3ce44SJohn Forte * LU abort successfully
5011fcf3ce44SJohn Forte */
5012fcf3ce44SJohn Forte atomic_and_32(&itask->itask_flags, ~ITASK_KNOWN_TO_LU);
5013fcf3ce44SJohn Forte return;
5014fcf3ce44SJohn Forte }
5015fcf3ce44SJohn Forte
5016fcf3ce44SJohn Forte stmf_abort_task_offline(task, 1, info);
5017fcf3ce44SJohn Forte }
5018fcf3ce44SJohn Forte
5019fcf3ce44SJohn Forte void
stmf_task_lport_aborted(scsi_task_t * task,stmf_status_t s,uint32_t iof)5020fcf3ce44SJohn Forte stmf_task_lport_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof)
5021fcf3ce44SJohn Forte {
5022fcf3ce44SJohn Forte char info[STMF_CHANGE_INFO_LEN];
5023fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask = TASK_TO_ITASK(task);
5024fcf3ce44SJohn Forte unsigned long long st;
5025554c2b16Stim szeto uint32_t old, new;
5026fcf3ce44SJohn Forte
502740c3e8ffSJohn Forte stmf_task_audit(itask, TE_TASK_LPORT_ABORTED, iof, NULL);
502840c3e8ffSJohn Forte
5029fcf3ce44SJohn Forte st = s;
5030fcf3ce44SJohn Forte if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) {
50314558d122SViswanathan Kannappan (void) snprintf(info, sizeof (info),
5032fcf3ce44SJohn Forte "task %p, tgt port failed to abort ret=%llx", (void *)task,
5033fcf3ce44SJohn Forte st);
5034fcf3ce44SJohn Forte } else if ((iof & STMF_IOF_LPORT_DONE) == 0) {
50354558d122SViswanathan Kannappan (void) snprintf(info, sizeof (info),
5036fcf3ce44SJohn Forte "Task aborted but tgt port is not finished, "
5037fcf3ce44SJohn Forte "task=%p, s=%llx, iof=%x", (void *)task, st, iof);
5038fcf3ce44SJohn Forte } else {
5039fcf3ce44SJohn Forte /*
5040554c2b16Stim szeto * LPORT abort successfully
5041fcf3ce44SJohn Forte */
5042554c2b16Stim szeto do {
5043554c2b16Stim szeto old = new = itask->itask_flags;
5044554c2b16Stim szeto if (!(old & ITASK_KNOWN_TO_TGT_PORT))
5045554c2b16Stim szeto return;
5046554c2b16Stim szeto new &= ~ITASK_KNOWN_TO_TGT_PORT;
5047554c2b16Stim szeto } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5048fcf3ce44SJohn Forte return;
5049fcf3ce44SJohn Forte }
5050fcf3ce44SJohn Forte
5051fcf3ce44SJohn Forte stmf_abort_task_offline(task, 0, info);
5052fcf3ce44SJohn Forte }
5053fcf3ce44SJohn Forte
5054fcf3ce44SJohn Forte stmf_status_t
stmf_task_poll_lu(scsi_task_t * task,uint32_t timeout)5055fcf3ce44SJohn Forte stmf_task_poll_lu(scsi_task_t *task, uint32_t timeout)
5056fcf3ce44SJohn Forte {
5057fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
5058fcf3ce44SJohn Forte task->task_stmf_private;
5059fcf3ce44SJohn Forte stmf_worker_t *w = itask->itask_worker;
5060fcf3ce44SJohn Forte int i;
5061fcf3ce44SJohn Forte
5062fcf3ce44SJohn Forte ASSERT(itask->itask_flags & ITASK_KNOWN_TO_LU);
5063fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
5064fcf3ce44SJohn Forte if (itask->itask_ncmds >= ITASK_MAX_NCMDS) {
5065fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
5066fcf3ce44SJohn Forte return (STMF_BUSY);
5067fcf3ce44SJohn Forte }
5068fcf3ce44SJohn Forte for (i = 0; i < itask->itask_ncmds; i++) {
5069fcf3ce44SJohn Forte if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LU) {
5070fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
5071fcf3ce44SJohn Forte return (STMF_SUCCESS);
5072fcf3ce44SJohn Forte }
5073fcf3ce44SJohn Forte }
5074fcf3ce44SJohn Forte itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LU;
5075fcf3ce44SJohn Forte if (timeout == ITASK_DEFAULT_POLL_TIMEOUT) {
5076fcf3ce44SJohn Forte itask->itask_poll_timeout = ddi_get_lbolt() + 1;
5077fcf3ce44SJohn Forte } else {
5078fcf3ce44SJohn Forte clock_t t = drv_usectohz(timeout * 1000);
5079fcf3ce44SJohn Forte if (t == 0)
5080fcf3ce44SJohn Forte t = 1;
5081fcf3ce44SJohn Forte itask->itask_poll_timeout = ddi_get_lbolt() + t;
5082fcf3ce44SJohn Forte }
5083fcf3ce44SJohn Forte if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) {
5084fcf3ce44SJohn Forte itask->itask_worker_next = NULL;
5085fcf3ce44SJohn Forte if (w->worker_task_tail) {
5086fcf3ce44SJohn Forte w->worker_task_tail->itask_worker_next = itask;
5087fcf3ce44SJohn Forte } else {
5088fcf3ce44SJohn Forte w->worker_task_head = itask;
5089fcf3ce44SJohn Forte }
5090fcf3ce44SJohn Forte w->worker_task_tail = itask;
5091fcf3ce44SJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
5092fcf3ce44SJohn Forte w->worker_max_qdepth_pu = w->worker_queue_depth;
5093fcf3ce44SJohn Forte }
5094fcf3ce44SJohn Forte atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE);
5095fcf3ce44SJohn Forte if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
5096fcf3ce44SJohn Forte cv_signal(&w->worker_cv);
5097fcf3ce44SJohn Forte }
5098fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
5099fcf3ce44SJohn Forte return (STMF_SUCCESS);
5100fcf3ce44SJohn Forte }
5101fcf3ce44SJohn Forte
5102fcf3ce44SJohn Forte stmf_status_t
stmf_task_poll_lport(scsi_task_t * task,uint32_t timeout)5103fcf3ce44SJohn Forte stmf_task_poll_lport(scsi_task_t *task, uint32_t timeout)
5104fcf3ce44SJohn Forte {
5105fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
5106fcf3ce44SJohn Forte task->task_stmf_private;
5107fcf3ce44SJohn Forte stmf_worker_t *w = itask->itask_worker;
5108fcf3ce44SJohn Forte int i;
5109fcf3ce44SJohn Forte
5110fcf3ce44SJohn Forte ASSERT(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT);
5111fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
5112fcf3ce44SJohn Forte if (itask->itask_ncmds >= ITASK_MAX_NCMDS) {
5113fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
5114fcf3ce44SJohn Forte return (STMF_BUSY);
5115fcf3ce44SJohn Forte }
5116fcf3ce44SJohn Forte for (i = 0; i < itask->itask_ncmds; i++) {
5117fcf3ce44SJohn Forte if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LPORT) {
5118fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
5119fcf3ce44SJohn Forte return (STMF_SUCCESS);
5120fcf3ce44SJohn Forte }
5121fcf3ce44SJohn Forte }
5122fcf3ce44SJohn Forte itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LPORT;
5123fcf3ce44SJohn Forte if (timeout == ITASK_DEFAULT_POLL_TIMEOUT) {
5124fcf3ce44SJohn Forte itask->itask_poll_timeout = ddi_get_lbolt() + 1;
5125fcf3ce44SJohn Forte } else {
5126fcf3ce44SJohn Forte clock_t t = drv_usectohz(timeout * 1000);
5127fcf3ce44SJohn Forte if (t == 0)
5128fcf3ce44SJohn Forte t = 1;
5129fcf3ce44SJohn Forte itask->itask_poll_timeout = ddi_get_lbolt() + t;
5130fcf3ce44SJohn Forte }
5131fcf3ce44SJohn Forte if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) {
5132fcf3ce44SJohn Forte itask->itask_worker_next = NULL;
5133fcf3ce44SJohn Forte if (w->worker_task_tail) {
5134fcf3ce44SJohn Forte w->worker_task_tail->itask_worker_next = itask;
5135fcf3ce44SJohn Forte } else {
5136fcf3ce44SJohn Forte w->worker_task_head = itask;
5137fcf3ce44SJohn Forte }
5138fcf3ce44SJohn Forte w->worker_task_tail = itask;
5139fcf3ce44SJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
5140fcf3ce44SJohn Forte w->worker_max_qdepth_pu = w->worker_queue_depth;
5141fcf3ce44SJohn Forte }
5142fcf3ce44SJohn Forte if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
5143fcf3ce44SJohn Forte cv_signal(&w->worker_cv);
5144fcf3ce44SJohn Forte }
5145fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
5146fcf3ce44SJohn Forte return (STMF_SUCCESS);
5147fcf3ce44SJohn Forte }
5148fcf3ce44SJohn Forte
5149fcf3ce44SJohn Forte void
stmf_do_task_abort(scsi_task_t * task)5150fcf3ce44SJohn Forte stmf_do_task_abort(scsi_task_t *task)
5151fcf3ce44SJohn Forte {
5152fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask = TASK_TO_ITASK(task);
5153fcf3ce44SJohn Forte stmf_lu_t *lu;
5154fcf3ce44SJohn Forte stmf_local_port_t *lport;
5155fcf3ce44SJohn Forte unsigned long long ret;
5156fcf3ce44SJohn Forte uint32_t old, new;
5157fcf3ce44SJohn Forte uint8_t call_lu_abort, call_port_abort;
5158fcf3ce44SJohn Forte char info[STMF_CHANGE_INFO_LEN];
5159fcf3ce44SJohn Forte
5160fcf3ce44SJohn Forte lu = task->task_lu;
5161fcf3ce44SJohn Forte lport = task->task_lport;
5162fcf3ce44SJohn Forte do {
5163fcf3ce44SJohn Forte old = new = itask->itask_flags;
5164fcf3ce44SJohn Forte if ((old & (ITASK_KNOWN_TO_LU | ITASK_LU_ABORT_CALLED)) ==
5165fcf3ce44SJohn Forte ITASK_KNOWN_TO_LU) {
5166fcf3ce44SJohn Forte new |= ITASK_LU_ABORT_CALLED;
5167fcf3ce44SJohn Forte call_lu_abort = 1;
5168fcf3ce44SJohn Forte } else {
5169fcf3ce44SJohn Forte call_lu_abort = 0;
5170fcf3ce44SJohn Forte }
5171fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5172fcf3ce44SJohn Forte
5173fcf3ce44SJohn Forte if (call_lu_abort) {
5174fcf3ce44SJohn Forte if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0) {
5175fcf3ce44SJohn Forte ret = lu->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0);
5176fcf3ce44SJohn Forte } else {
5177fcf3ce44SJohn Forte ret = dlun0->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0);
5178fcf3ce44SJohn Forte }
5179fcf3ce44SJohn Forte if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) {
5180fcf3ce44SJohn Forte stmf_task_lu_aborted(task, ret, STMF_IOF_LU_DONE);
5181fcf3ce44SJohn Forte } else if (ret == STMF_BUSY) {
5182fcf3ce44SJohn Forte atomic_and_32(&itask->itask_flags,
5183fcf3ce44SJohn Forte ~ITASK_LU_ABORT_CALLED);
5184fcf3ce44SJohn Forte } else if (ret != STMF_SUCCESS) {
51854558d122SViswanathan Kannappan (void) snprintf(info, sizeof (info),
5186fcf3ce44SJohn Forte "Abort failed by LU %p, ret %llx", (void *)lu, ret);
5187fcf3ce44SJohn Forte stmf_abort_task_offline(task, 1, info);
5188fcf3ce44SJohn Forte }
5189fcf3ce44SJohn Forte } else if (itask->itask_flags & ITASK_KNOWN_TO_LU) {
5190fcf3ce44SJohn Forte if (ddi_get_lbolt() > (itask->itask_start_time +
5191fcf3ce44SJohn Forte STMF_SEC2TICK(lu->lu_abort_timeout?
5192fcf3ce44SJohn Forte lu->lu_abort_timeout : ITASK_DEFAULT_ABORT_TIMEOUT))) {
51934558d122SViswanathan Kannappan (void) snprintf(info, sizeof (info),
5194fcf3ce44SJohn Forte "lu abort timed out");
5195fcf3ce44SJohn Forte stmf_abort_task_offline(itask->itask_task, 1, info);
5196fcf3ce44SJohn Forte }
5197fcf3ce44SJohn Forte }
5198fcf3ce44SJohn Forte
5199fcf3ce44SJohn Forte do {
5200fcf3ce44SJohn Forte old = new = itask->itask_flags;
5201fcf3ce44SJohn Forte if ((old & (ITASK_KNOWN_TO_TGT_PORT |
5202fcf3ce44SJohn Forte ITASK_TGT_PORT_ABORT_CALLED)) == ITASK_KNOWN_TO_TGT_PORT) {
5203fcf3ce44SJohn Forte new |= ITASK_TGT_PORT_ABORT_CALLED;
5204fcf3ce44SJohn Forte call_port_abort = 1;
5205fcf3ce44SJohn Forte } else {
5206fcf3ce44SJohn Forte call_port_abort = 0;
5207fcf3ce44SJohn Forte }
5208fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5209fcf3ce44SJohn Forte if (call_port_abort) {
52105679c89fSjv227347 ret = lport->lport_abort(lport, STMF_LPORT_ABORT_TASK, task, 0);
5211fcf3ce44SJohn Forte if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) {
5212fcf3ce44SJohn Forte stmf_task_lport_aborted(task, ret, STMF_IOF_LPORT_DONE);
5213fcf3ce44SJohn Forte } else if (ret == STMF_BUSY) {
5214fcf3ce44SJohn Forte atomic_and_32(&itask->itask_flags,
5215fcf3ce44SJohn Forte ~ITASK_TGT_PORT_ABORT_CALLED);
5216fcf3ce44SJohn Forte } else if (ret != STMF_SUCCESS) {
52174558d122SViswanathan Kannappan (void) snprintf(info, sizeof (info),
5218fcf3ce44SJohn Forte "Abort failed by tgt port %p ret %llx",
5219fcf3ce44SJohn Forte (void *)lport, ret);
5220fcf3ce44SJohn Forte stmf_abort_task_offline(task, 0, info);
5221fcf3ce44SJohn Forte }
5222fcf3ce44SJohn Forte } else if (itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT) {
5223fcf3ce44SJohn Forte if (ddi_get_lbolt() > (itask->itask_start_time +
5224fcf3ce44SJohn Forte STMF_SEC2TICK(lport->lport_abort_timeout?
5225fcf3ce44SJohn Forte lport->lport_abort_timeout :
5226fcf3ce44SJohn Forte ITASK_DEFAULT_ABORT_TIMEOUT))) {
52274558d122SViswanathan Kannappan (void) snprintf(info, sizeof (info),
5228fcf3ce44SJohn Forte "lport abort timed out");
5229fcf3ce44SJohn Forte stmf_abort_task_offline(itask->itask_task, 0, info);
5230fcf3ce44SJohn Forte }
5231fcf3ce44SJohn Forte }
5232fcf3ce44SJohn Forte }
5233fcf3ce44SJohn Forte
5234fcf3ce44SJohn Forte stmf_status_t
stmf_ctl(int cmd,void * obj,void * arg)5235fcf3ce44SJohn Forte stmf_ctl(int cmd, void *obj, void *arg)
5236fcf3ce44SJohn Forte {
5237fcf3ce44SJohn Forte stmf_status_t ret;
5238fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
5239fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
5240fcf3ce44SJohn Forte stmf_state_change_info_t *ssci = (stmf_state_change_info_t *)arg;
5241fcf3ce44SJohn Forte
5242fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
5243fcf3ce44SJohn Forte ret = STMF_INVALID_ARG;
5244fcf3ce44SJohn Forte if (cmd & STMF_CMD_LU_OP) {
5245fcf3ce44SJohn Forte ilu = stmf_lookup_lu((stmf_lu_t *)obj);
5246fcf3ce44SJohn Forte if (ilu == NULL) {
5247fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5248fcf3ce44SJohn Forte }
5249e17f3b22Stim szeto DTRACE_PROBE3(lu__state__change,
5250e17f3b22Stim szeto stmf_lu_t *, ilu->ilu_lu,
5251e17f3b22Stim szeto int, cmd, stmf_state_change_info_t *, ssci);
5252fcf3ce44SJohn Forte } else if (cmd & STMF_CMD_LPORT_OP) {
5253fcf3ce44SJohn Forte ilport = stmf_lookup_lport((stmf_local_port_t *)obj);
5254fcf3ce44SJohn Forte if (ilport == NULL) {
5255fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5256fcf3ce44SJohn Forte }
5257e17f3b22Stim szeto DTRACE_PROBE3(lport__state__change,
5258e17f3b22Stim szeto stmf_local_port_t *, ilport->ilport_lport,
5259e17f3b22Stim szeto int, cmd, stmf_state_change_info_t *, ssci);
5260fcf3ce44SJohn Forte } else {
5261fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5262fcf3ce44SJohn Forte }
5263fcf3ce44SJohn Forte
5264fcf3ce44SJohn Forte switch (cmd) {
5265fcf3ce44SJohn Forte case STMF_CMD_LU_ONLINE:
52664f486358SNattuvetty Bhavyan switch (ilu->ilu_state) {
52674f486358SNattuvetty Bhavyan case STMF_STATE_OFFLINE:
52684f486358SNattuvetty Bhavyan ret = STMF_SUCCESS;
52694f486358SNattuvetty Bhavyan break;
52704f486358SNattuvetty Bhavyan case STMF_STATE_ONLINE:
52714f486358SNattuvetty Bhavyan case STMF_STATE_ONLINING:
5272fcf3ce44SJohn Forte ret = STMF_ALREADY;
52734f486358SNattuvetty Bhavyan break;
52744f486358SNattuvetty Bhavyan case STMF_STATE_OFFLINING:
52754f486358SNattuvetty Bhavyan ret = STMF_BUSY;
52764f486358SNattuvetty Bhavyan break;
52774f486358SNattuvetty Bhavyan default:
52784f486358SNattuvetty Bhavyan ret = STMF_BADSTATE;
52794f486358SNattuvetty Bhavyan break;
5280fcf3ce44SJohn Forte }
52814f486358SNattuvetty Bhavyan if (ret != STMF_SUCCESS)
5282fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
52834f486358SNattuvetty Bhavyan
5284fcf3ce44SJohn Forte ilu->ilu_state = STMF_STATE_ONLINING;
5285fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5286fcf3ce44SJohn Forte stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5287fcf3ce44SJohn Forte break;
5288fcf3ce44SJohn Forte
5289fcf3ce44SJohn Forte case STMF_CMD_LU_ONLINE_COMPLETE:
5290fcf3ce44SJohn Forte if (ilu->ilu_state != STMF_STATE_ONLINING) {
52914f486358SNattuvetty Bhavyan ret = STMF_BADSTATE;
5292fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5293fcf3ce44SJohn Forte }
5294fcf3ce44SJohn Forte if (((stmf_change_status_t *)arg)->st_completion_status ==
5295fcf3ce44SJohn Forte STMF_SUCCESS) {
5296fcf3ce44SJohn Forte ilu->ilu_state = STMF_STATE_ONLINE;
5297fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5298fcf3ce44SJohn Forte ((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj,
5299fcf3ce44SJohn Forte STMF_ACK_LU_ONLINE_COMPLETE, arg);
5300fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
5301fcf3ce44SJohn Forte stmf_add_lu_to_active_sessions((stmf_lu_t *)obj);
5302fcf3ce44SJohn Forte } else {
5303fcf3ce44SJohn Forte /* XXX: should throw a meesage an record more data */
5304fcf3ce44SJohn Forte ilu->ilu_state = STMF_STATE_OFFLINE;
5305fcf3ce44SJohn Forte }
5306fcf3ce44SJohn Forte ret = STMF_SUCCESS;
5307fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5308fcf3ce44SJohn Forte
5309fcf3ce44SJohn Forte case STMF_CMD_LU_OFFLINE:
53104f486358SNattuvetty Bhavyan switch (ilu->ilu_state) {
53114f486358SNattuvetty Bhavyan case STMF_STATE_ONLINE:
53124f486358SNattuvetty Bhavyan ret = STMF_SUCCESS;
53134f486358SNattuvetty Bhavyan break;
53144f486358SNattuvetty Bhavyan case STMF_STATE_OFFLINE:
53154f486358SNattuvetty Bhavyan case STMF_STATE_OFFLINING:
5316fcf3ce44SJohn Forte ret = STMF_ALREADY;
53174f486358SNattuvetty Bhavyan break;
53184f486358SNattuvetty Bhavyan case STMF_STATE_ONLINING:
53194f486358SNattuvetty Bhavyan ret = STMF_BUSY;
53204f486358SNattuvetty Bhavyan break;
53214f486358SNattuvetty Bhavyan default:
53224f486358SNattuvetty Bhavyan ret = STMF_BADSTATE;
53234f486358SNattuvetty Bhavyan break;
5324fcf3ce44SJohn Forte }
53254f486358SNattuvetty Bhavyan if (ret != STMF_SUCCESS)
5326fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5327fcf3ce44SJohn Forte ilu->ilu_state = STMF_STATE_OFFLINING;
5328fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5329fcf3ce44SJohn Forte stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5330fcf3ce44SJohn Forte break;
5331fcf3ce44SJohn Forte
5332fcf3ce44SJohn Forte case STMF_CMD_LU_OFFLINE_COMPLETE:
5333fcf3ce44SJohn Forte if (ilu->ilu_state != STMF_STATE_OFFLINING) {
53344f486358SNattuvetty Bhavyan ret = STMF_BADSTATE;
5335fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5336fcf3ce44SJohn Forte }
5337fcf3ce44SJohn Forte if (((stmf_change_status_t *)arg)->st_completion_status ==
5338fcf3ce44SJohn Forte STMF_SUCCESS) {
5339fcf3ce44SJohn Forte ilu->ilu_state = STMF_STATE_OFFLINE;
5340fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5341fcf3ce44SJohn Forte ((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj,
5342fcf3ce44SJohn Forte STMF_ACK_LU_OFFLINE_COMPLETE, arg);
5343fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
5344fcf3ce44SJohn Forte } else {
5345fcf3ce44SJohn Forte ilu->ilu_state = STMF_STATE_ONLINE;
5346fcf3ce44SJohn Forte stmf_add_lu_to_active_sessions((stmf_lu_t *)obj);
5347fcf3ce44SJohn Forte }
5348fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5349fcf3ce44SJohn Forte break;
5350fcf3ce44SJohn Forte
5351fcf3ce44SJohn Forte /*
5352fcf3ce44SJohn Forte * LPORT_ONLINE/OFFLINE has nothing to do with link offline/online.
5353fcf3ce44SJohn Forte * It's related with hardware disable/enable.
5354fcf3ce44SJohn Forte */
5355fcf3ce44SJohn Forte case STMF_CMD_LPORT_ONLINE:
53564f486358SNattuvetty Bhavyan switch (ilport->ilport_state) {
53574f486358SNattuvetty Bhavyan case STMF_STATE_OFFLINE:
53584f486358SNattuvetty Bhavyan ret = STMF_SUCCESS;
53594f486358SNattuvetty Bhavyan break;
53604f486358SNattuvetty Bhavyan case STMF_STATE_ONLINE:
53614f486358SNattuvetty Bhavyan case STMF_STATE_ONLINING:
5362fcf3ce44SJohn Forte ret = STMF_ALREADY;
53634f486358SNattuvetty Bhavyan break;
53644f486358SNattuvetty Bhavyan case STMF_STATE_OFFLINING:
53654f486358SNattuvetty Bhavyan ret = STMF_BUSY;
53664f486358SNattuvetty Bhavyan break;
53674f486358SNattuvetty Bhavyan default:
53684f486358SNattuvetty Bhavyan ret = STMF_BADSTATE;
53694f486358SNattuvetty Bhavyan break;
5370fcf3ce44SJohn Forte }
53714f486358SNattuvetty Bhavyan if (ret != STMF_SUCCESS)
5372fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5373fcf3ce44SJohn Forte
5374fcf3ce44SJohn Forte /*
5375fcf3ce44SJohn Forte * Only user request can recover the port from the
5376fcf3ce44SJohn Forte * FORCED_OFFLINE state
5377fcf3ce44SJohn Forte */
5378fcf3ce44SJohn Forte if (ilport->ilport_flags & ILPORT_FORCED_OFFLINE) {
5379fcf3ce44SJohn Forte if (!(ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) {
5380fcf3ce44SJohn Forte ret = STMF_FAILURE;
5381fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5382fcf3ce44SJohn Forte }
5383fcf3ce44SJohn Forte }
5384fcf3ce44SJohn Forte
5385fcf3ce44SJohn Forte /*
5386fcf3ce44SJohn Forte * Avoid too frequent request to online
5387fcf3ce44SJohn Forte */
5388fcf3ce44SJohn Forte if (ssci->st_rflags & STMF_RFLAG_USER_REQUEST) {
5389fcf3ce44SJohn Forte ilport->ilport_online_times = 0;
5390fcf3ce44SJohn Forte ilport->ilport_avg_interval = 0;
5391fcf3ce44SJohn Forte }
5392fcf3ce44SJohn Forte if ((ilport->ilport_avg_interval < STMF_AVG_ONLINE_INTERVAL) &&
5393fcf3ce44SJohn Forte (ilport->ilport_online_times >= 4)) {
5394fcf3ce44SJohn Forte ret = STMF_FAILURE;
5395fcf3ce44SJohn Forte ilport->ilport_flags |= ILPORT_FORCED_OFFLINE;
5396fcf3ce44SJohn Forte stmf_trace(NULL, "stmf_ctl: too frequent request to "
5397fcf3ce44SJohn Forte "online the port");
5398fcf3ce44SJohn Forte cmn_err(CE_WARN, "stmf_ctl: too frequent request to "
5399fcf3ce44SJohn Forte "online the port, set FORCED_OFFLINE now");
5400fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5401fcf3ce44SJohn Forte }
5402fcf3ce44SJohn Forte if (ilport->ilport_online_times > 0) {
5403fcf3ce44SJohn Forte if (ilport->ilport_online_times == 1) {
5404fcf3ce44SJohn Forte ilport->ilport_avg_interval = ddi_get_lbolt() -
5405fcf3ce44SJohn Forte ilport->ilport_last_online_clock;
5406fcf3ce44SJohn Forte } else {
5407fcf3ce44SJohn Forte ilport->ilport_avg_interval =
5408fcf3ce44SJohn Forte (ilport->ilport_avg_interval +
5409fcf3ce44SJohn Forte ddi_get_lbolt() -
5410fcf3ce44SJohn Forte ilport->ilport_last_online_clock) >> 1;
5411fcf3ce44SJohn Forte }
5412fcf3ce44SJohn Forte }
5413fcf3ce44SJohn Forte ilport->ilport_last_online_clock = ddi_get_lbolt();
5414fcf3ce44SJohn Forte ilport->ilport_online_times++;
5415fcf3ce44SJohn Forte
5416fcf3ce44SJohn Forte /*
5417fcf3ce44SJohn Forte * Submit online service request
5418fcf3ce44SJohn Forte */
5419fcf3ce44SJohn Forte ilport->ilport_flags &= ~ILPORT_FORCED_OFFLINE;
5420fcf3ce44SJohn Forte ilport->ilport_state = STMF_STATE_ONLINING;
5421fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5422fcf3ce44SJohn Forte stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5423fcf3ce44SJohn Forte break;
5424fcf3ce44SJohn Forte
5425fcf3ce44SJohn Forte case STMF_CMD_LPORT_ONLINE_COMPLETE:
5426fcf3ce44SJohn Forte if (ilport->ilport_state != STMF_STATE_ONLINING) {
54274f486358SNattuvetty Bhavyan ret = STMF_BADSTATE;
5428fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5429fcf3ce44SJohn Forte }
5430fcf3ce44SJohn Forte if (((stmf_change_status_t *)arg)->st_completion_status ==
5431fcf3ce44SJohn Forte STMF_SUCCESS) {
5432fcf3ce44SJohn Forte ilport->ilport_state = STMF_STATE_ONLINE;
5433fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5434fcf3ce44SJohn Forte ((stmf_local_port_t *)obj)->lport_ctl(
5435fcf3ce44SJohn Forte (stmf_local_port_t *)obj,
5436fcf3ce44SJohn Forte STMF_ACK_LPORT_ONLINE_COMPLETE, arg);
5437fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
5438fcf3ce44SJohn Forte } else {
5439fcf3ce44SJohn Forte ilport->ilport_state = STMF_STATE_OFFLINE;
5440fcf3ce44SJohn Forte }
5441fcf3ce44SJohn Forte ret = STMF_SUCCESS;
5442fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5443fcf3ce44SJohn Forte
5444fcf3ce44SJohn Forte case STMF_CMD_LPORT_OFFLINE:
54454f486358SNattuvetty Bhavyan switch (ilport->ilport_state) {
54464f486358SNattuvetty Bhavyan case STMF_STATE_ONLINE:
54474f486358SNattuvetty Bhavyan ret = STMF_SUCCESS;
54484f486358SNattuvetty Bhavyan break;
54494f486358SNattuvetty Bhavyan case STMF_STATE_OFFLINE:
54504f486358SNattuvetty Bhavyan case STMF_STATE_OFFLINING:
5451fcf3ce44SJohn Forte ret = STMF_ALREADY;
54524f486358SNattuvetty Bhavyan break;
54534f486358SNattuvetty Bhavyan case STMF_STATE_ONLINING:
54544f486358SNattuvetty Bhavyan ret = STMF_BUSY;
54554f486358SNattuvetty Bhavyan break;
54564f486358SNattuvetty Bhavyan default:
54574f486358SNattuvetty Bhavyan ret = STMF_BADSTATE;
54584f486358SNattuvetty Bhavyan break;
5459fcf3ce44SJohn Forte }
54604f486358SNattuvetty Bhavyan if (ret != STMF_SUCCESS)
5461fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
54624f486358SNattuvetty Bhavyan
5463fcf3ce44SJohn Forte ilport->ilport_state = STMF_STATE_OFFLINING;
5464fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5465fcf3ce44SJohn Forte stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
5466fcf3ce44SJohn Forte break;
5467fcf3ce44SJohn Forte
5468fcf3ce44SJohn Forte case STMF_CMD_LPORT_OFFLINE_COMPLETE:
5469fcf3ce44SJohn Forte if (ilport->ilport_state != STMF_STATE_OFFLINING) {
54704f486358SNattuvetty Bhavyan ret = STMF_BADSTATE;
5471fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5472fcf3ce44SJohn Forte }
5473fcf3ce44SJohn Forte if (((stmf_change_status_t *)arg)->st_completion_status ==
5474fcf3ce44SJohn Forte STMF_SUCCESS) {
5475fcf3ce44SJohn Forte ilport->ilport_state = STMF_STATE_OFFLINE;
5476fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5477fcf3ce44SJohn Forte ((stmf_local_port_t *)obj)->lport_ctl(
5478fcf3ce44SJohn Forte (stmf_local_port_t *)obj,
5479fcf3ce44SJohn Forte STMF_ACK_LPORT_OFFLINE_COMPLETE, arg);
5480fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
5481fcf3ce44SJohn Forte } else {
5482fcf3ce44SJohn Forte ilport->ilport_state = STMF_STATE_ONLINE;
5483fcf3ce44SJohn Forte }
5484fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5485fcf3ce44SJohn Forte break;
5486fcf3ce44SJohn Forte
5487fcf3ce44SJohn Forte default:
5488fcf3ce44SJohn Forte cmn_err(CE_WARN, "Invalid ctl cmd received %x", cmd);
5489fcf3ce44SJohn Forte ret = STMF_INVALID_ARG;
5490fcf3ce44SJohn Forte goto stmf_ctl_lock_exit;
5491fcf3ce44SJohn Forte }
5492fcf3ce44SJohn Forte
5493fcf3ce44SJohn Forte return (STMF_SUCCESS);
5494fcf3ce44SJohn Forte
5495fcf3ce44SJohn Forte stmf_ctl_lock_exit:;
5496fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5497fcf3ce44SJohn Forte return (ret);
5498fcf3ce44SJohn Forte }
5499fcf3ce44SJohn Forte
5500fcf3ce44SJohn Forte /* ARGSUSED */
5501fcf3ce44SJohn Forte stmf_status_t
stmf_info_impl(uint32_t cmd,void * arg1,void * arg2,uint8_t * buf,uint32_t * bufsizep)5502fcf3ce44SJohn Forte stmf_info_impl(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf,
5503fcf3ce44SJohn Forte uint32_t *bufsizep)
5504fcf3ce44SJohn Forte {
5505fcf3ce44SJohn Forte return (STMF_NOT_SUPPORTED);
5506fcf3ce44SJohn Forte }
5507fcf3ce44SJohn Forte
5508fcf3ce44SJohn Forte /* ARGSUSED */
5509fcf3ce44SJohn Forte stmf_status_t
stmf_info(uint32_t cmd,void * arg1,void * arg2,uint8_t * buf,uint32_t * bufsizep)5510fcf3ce44SJohn Forte stmf_info(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf,
5511fcf3ce44SJohn Forte uint32_t *bufsizep)
5512fcf3ce44SJohn Forte {
5513fcf3ce44SJohn Forte uint32_t cl = SI_GET_CLASS(cmd);
5514fcf3ce44SJohn Forte
5515fcf3ce44SJohn Forte if (cl == SI_STMF) {
5516fcf3ce44SJohn Forte return (stmf_info_impl(cmd, arg1, arg2, buf, bufsizep));
5517fcf3ce44SJohn Forte }
5518fcf3ce44SJohn Forte if (cl == SI_LPORT) {
55195679c89fSjv227347 return (((stmf_local_port_t *)arg1)->lport_info(cmd, arg1,
55205679c89fSjv227347 arg2, buf, bufsizep));
5521fcf3ce44SJohn Forte } else if (cl == SI_LU) {
55225679c89fSjv227347 return (((stmf_lu_t *)arg1)->lu_info(cmd, arg1, arg2, buf,
55235679c89fSjv227347 bufsizep));
5524fcf3ce44SJohn Forte }
5525fcf3ce44SJohn Forte
5526fcf3ce44SJohn Forte return (STMF_NOT_SUPPORTED);
5527fcf3ce44SJohn Forte }
5528fcf3ce44SJohn Forte
5529fcf3ce44SJohn Forte /*
553070c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States * Used by port providers. pwwn is 8 byte wwn, sdid is the devid used by
5531fcf3ce44SJohn Forte * stmf to register local ports. The ident should have 20 bytes in buffer
5532fcf3ce44SJohn Forte * space to convert the wwn to "wwn.xxxxxxxxxxxxxxxx" string.
5533fcf3ce44SJohn Forte */
5534fcf3ce44SJohn Forte void
stmf_wwn_to_devid_desc(scsi_devid_desc_t * sdid,uint8_t * wwn,uint8_t protocol_id)5535fcf3ce44SJohn Forte stmf_wwn_to_devid_desc(scsi_devid_desc_t *sdid, uint8_t *wwn,
5536fcf3ce44SJohn Forte uint8_t protocol_id)
5537fcf3ce44SJohn Forte {
553870c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States char wwn_str[20+1];
553970c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States
5540fcf3ce44SJohn Forte sdid->protocol_id = protocol_id;
5541fcf3ce44SJohn Forte sdid->piv = 1;
5542fcf3ce44SJohn Forte sdid->code_set = CODE_SET_ASCII;
5543fcf3ce44SJohn Forte sdid->association = ID_IS_TARGET_PORT;
5544fcf3ce44SJohn Forte sdid->ident_length = 20;
554570c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States /* Convert wwn value to "wwn.XXXXXXXXXXXXXXXX" format */
554670c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States (void) snprintf(wwn_str, sizeof (wwn_str),
5547fcf3ce44SJohn Forte "wwn.%02X%02X%02X%02X%02X%02X%02X%02X",
5548fcf3ce44SJohn Forte wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
554970c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States bcopy(wwn_str, (char *)sdid->ident, 20);
5550fcf3ce44SJohn Forte }
5551fcf3ce44SJohn Forte
555270c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States
5553fcf3ce44SJohn Forte stmf_xfer_data_t *
stmf_prepare_tpgs_data(uint8_t ilu_alua)555445039663SJohn Forte stmf_prepare_tpgs_data(uint8_t ilu_alua)
5555fcf3ce44SJohn Forte {
5556fcf3ce44SJohn Forte stmf_xfer_data_t *xd;
5557fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
5558fcf3ce44SJohn Forte uint8_t *p;
555945039663SJohn Forte uint32_t sz, asz, nports = 0, nports_standby = 0;
5560fcf3ce44SJohn Forte
5561fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
556245039663SJohn Forte /* check if any ports are standby and create second group */
556345039663SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport;
556445039663SJohn Forte ilport = ilport->ilport_next) {
556545039663SJohn Forte if (ilport->ilport_standby == 1) {
556645039663SJohn Forte nports_standby++;
556745039663SJohn Forte } else {
556845039663SJohn Forte nports++;
556945039663SJohn Forte }
557045039663SJohn Forte }
557145039663SJohn Forte
557245039663SJohn Forte /* The spec only allows for 255 ports to be reported per group */
557345039663SJohn Forte nports = min(nports, 255);
557445039663SJohn Forte nports_standby = min(nports_standby, 255);
5575fcf3ce44SJohn Forte sz = (nports * 4) + 12;
557645039663SJohn Forte if (nports_standby && ilu_alua) {
557745039663SJohn Forte sz += (nports_standby * 4) + 8;
557845039663SJohn Forte }
5579fcf3ce44SJohn Forte asz = sz + sizeof (*xd) - 4;
5580fcf3ce44SJohn Forte xd = (stmf_xfer_data_t *)kmem_zalloc(asz, KM_NOSLEEP);
5581fcf3ce44SJohn Forte if (xd == NULL) {
5582fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5583fcf3ce44SJohn Forte return (NULL);
5584fcf3ce44SJohn Forte }
5585fcf3ce44SJohn Forte xd->alloc_size = asz;
5586fcf3ce44SJohn Forte xd->size_left = sz;
5587fcf3ce44SJohn Forte
5588fcf3ce44SJohn Forte p = xd->buf;
5589fcf3ce44SJohn Forte
5590fcf3ce44SJohn Forte *((uint32_t *)p) = BE_32(sz - 4);
5591fcf3ce44SJohn Forte p += 4;
5592fcf3ce44SJohn Forte p[0] = 0x80; /* PREF */
559345039663SJohn Forte p[1] = 5; /* AO_SUP, S_SUP */
559445039663SJohn Forte if (stmf_state.stmf_alua_node == 1) {
559545039663SJohn Forte p[3] = 1; /* Group 1 */
559645039663SJohn Forte } else {
559745039663SJohn Forte p[3] = 0; /* Group 0 */
559845039663SJohn Forte }
5599fcf3ce44SJohn Forte p[7] = nports & 0xff;
5600fcf3ce44SJohn Forte p += 8;
560145039663SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport;
560245039663SJohn Forte ilport = ilport->ilport_next) {
560345039663SJohn Forte if (ilport->ilport_standby == 1) {
560445039663SJohn Forte continue;
5605fcf3ce44SJohn Forte }
560645039663SJohn Forte ((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid);
560745039663SJohn Forte p += 4;
560845039663SJohn Forte }
560945039663SJohn Forte if (nports_standby && ilu_alua) {
561045039663SJohn Forte p[0] = 0x02; /* Non PREF, Standby */
561145039663SJohn Forte p[1] = 5; /* AO_SUP, S_SUP */
561245039663SJohn Forte if (stmf_state.stmf_alua_node == 1) {
561345039663SJohn Forte p[3] = 0; /* Group 0 */
561445039663SJohn Forte } else {
561545039663SJohn Forte p[3] = 1; /* Group 1 */
561645039663SJohn Forte }
561745039663SJohn Forte p[7] = nports_standby & 0xff;
561845039663SJohn Forte p += 8;
561945039663SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport;
562045039663SJohn Forte ilport = ilport->ilport_next) {
562145039663SJohn Forte if (ilport->ilport_standby == 0) {
562245039663SJohn Forte continue;
562345039663SJohn Forte }
562445039663SJohn Forte ((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid);
562545039663SJohn Forte p += 4;
562645039663SJohn Forte }
562745039663SJohn Forte }
562845039663SJohn Forte
5629fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5630fcf3ce44SJohn Forte
5631fcf3ce44SJohn Forte return (xd);
5632fcf3ce44SJohn Forte }
5633fcf3ce44SJohn Forte
56348fe96085Stim szeto struct scsi_devid_desc *
stmf_scsilib_get_devid_desc(uint16_t rtpid)56358fe96085Stim szeto stmf_scsilib_get_devid_desc(uint16_t rtpid)
56368fe96085Stim szeto {
56378fe96085Stim szeto scsi_devid_desc_t *devid = NULL;
56388fe96085Stim szeto stmf_i_local_port_t *ilport;
56398fe96085Stim szeto
56408fe96085Stim szeto mutex_enter(&stmf_state.stmf_lock);
56418fe96085Stim szeto
56428fe96085Stim szeto for (ilport = stmf_state.stmf_ilportlist; ilport;
56438fe96085Stim szeto ilport = ilport->ilport_next) {
56448fe96085Stim szeto if (ilport->ilport_rtpid == rtpid) {
56458fe96085Stim szeto scsi_devid_desc_t *id = ilport->ilport_lport->lport_id;
5646716c1805SNattuvetty Bhavyan uint32_t id_sz = sizeof (scsi_devid_desc_t) +
56478fe96085Stim szeto id->ident_length;
56488fe96085Stim szeto devid = (scsi_devid_desc_t *)kmem_zalloc(id_sz,
56498fe96085Stim szeto KM_NOSLEEP);
56508fe96085Stim szeto if (devid != NULL) {
56518fe96085Stim szeto bcopy(id, devid, id_sz);
56528fe96085Stim szeto }
56538fe96085Stim szeto break;
56548fe96085Stim szeto }
56558fe96085Stim szeto }
56568fe96085Stim szeto
56578fe96085Stim szeto mutex_exit(&stmf_state.stmf_lock);
56588fe96085Stim szeto return (devid);
56598fe96085Stim szeto }
56608fe96085Stim szeto
56618fe96085Stim szeto uint16_t
stmf_scsilib_get_lport_rtid(struct scsi_devid_desc * devid)56628fe96085Stim szeto stmf_scsilib_get_lport_rtid(struct scsi_devid_desc *devid)
56638fe96085Stim szeto {
56648fe96085Stim szeto stmf_i_local_port_t *ilport;
56658fe96085Stim szeto scsi_devid_desc_t *id;
56668fe96085Stim szeto uint16_t rtpid = 0;
56678fe96085Stim szeto
56688fe96085Stim szeto mutex_enter(&stmf_state.stmf_lock);
56698fe96085Stim szeto for (ilport = stmf_state.stmf_ilportlist; ilport;
56708fe96085Stim szeto ilport = ilport->ilport_next) {
56718fe96085Stim szeto id = ilport->ilport_lport->lport_id;
56728fe96085Stim szeto if ((devid->ident_length == id->ident_length) &&
56738fe96085Stim szeto (memcmp(devid->ident, id->ident, id->ident_length) == 0)) {
56748fe96085Stim szeto rtpid = ilport->ilport_rtpid;
56758fe96085Stim szeto break;
56768fe96085Stim szeto }
56778fe96085Stim szeto }
56788fe96085Stim szeto mutex_exit(&stmf_state.stmf_lock);
56798fe96085Stim szeto return (rtpid);
56808fe96085Stim szeto }
5681fcf3ce44SJohn Forte
5682fcf3ce44SJohn Forte static uint16_t stmf_lu_id_gen_number = 0;
5683fcf3ce44SJohn Forte
5684fcf3ce44SJohn Forte stmf_status_t
stmf_scsilib_uniq_lu_id(uint32_t company_id,scsi_devid_desc_t * lu_id)5685fcf3ce44SJohn Forte stmf_scsilib_uniq_lu_id(uint32_t company_id, scsi_devid_desc_t *lu_id)
5686fcf3ce44SJohn Forte {
5687fdcc480aSJohn Forte return (stmf_scsilib_uniq_lu_id2(company_id, 0, lu_id));
5688fdcc480aSJohn Forte }
5689fdcc480aSJohn Forte
5690fdcc480aSJohn Forte stmf_status_t
stmf_scsilib_uniq_lu_id2(uint32_t company_id,uint32_t host_id,scsi_devid_desc_t * lu_id)5691fdcc480aSJohn Forte stmf_scsilib_uniq_lu_id2(uint32_t company_id, uint32_t host_id,
5692fdcc480aSJohn Forte scsi_devid_desc_t *lu_id)
5693fdcc480aSJohn Forte {
5694fcf3ce44SJohn Forte uint8_t *p;
5695fcf3ce44SJohn Forte struct timeval32 timestamp32;
5696fcf3ce44SJohn Forte uint32_t *t = (uint32_t *)×tamp32;
5697fcf3ce44SJohn Forte struct ether_addr mac;
5698fcf3ce44SJohn Forte uint8_t *e = (uint8_t *)&mac;
5699fdcc480aSJohn Forte int hid = (int)host_id;
570057ff5e7eSJeff Biseda uint16_t gen_number;
5701fcf3ce44SJohn Forte
5702fcf3ce44SJohn Forte if (company_id == COMPANY_ID_NONE)
5703fcf3ce44SJohn Forte company_id = COMPANY_ID_SUN;
5704fcf3ce44SJohn Forte
5705fcf3ce44SJohn Forte if (lu_id->ident_length != 0x10)
5706fcf3ce44SJohn Forte return (STMF_INVALID_ARG);
5707fcf3ce44SJohn Forte
5708fcf3ce44SJohn Forte p = (uint8_t *)lu_id;
5709fcf3ce44SJohn Forte
57101a5e258fSJosef 'Jeff' Sipek gen_number = atomic_inc_16_nv(&stmf_lu_id_gen_number);
5711fcf3ce44SJohn Forte
5712fcf3ce44SJohn Forte p[0] = 0xf1; p[1] = 3; p[2] = 0; p[3] = 0x10;
5713fcf3ce44SJohn Forte p[4] = ((company_id >> 20) & 0xf) | 0x60;
5714fcf3ce44SJohn Forte p[5] = (company_id >> 12) & 0xff;
5715fcf3ce44SJohn Forte p[6] = (company_id >> 4) & 0xff;
5716fcf3ce44SJohn Forte p[7] = (company_id << 4) & 0xf0;
5717fdcc480aSJohn Forte if (hid == 0 && !localetheraddr((struct ether_addr *)NULL, &mac)) {
5718fdcc480aSJohn Forte hid = BE_32((int)zone_get_hostid(NULL));
5719fdcc480aSJohn Forte }
5720fdcc480aSJohn Forte if (hid != 0) {
5721fcf3ce44SJohn Forte e[0] = (hid >> 24) & 0xff;
5722fcf3ce44SJohn Forte e[1] = (hid >> 16) & 0xff;
5723fcf3ce44SJohn Forte e[2] = (hid >> 8) & 0xff;
5724fcf3ce44SJohn Forte e[3] = hid & 0xff;
5725fcf3ce44SJohn Forte e[4] = e[5] = 0;
5726fcf3ce44SJohn Forte }
5727fcf3ce44SJohn Forte bcopy(e, p+8, 6);
5728fcf3ce44SJohn Forte uniqtime32(×tamp32);
5729fcf3ce44SJohn Forte *t = BE_32(*t);
5730fcf3ce44SJohn Forte bcopy(t, p+14, 4);
573157ff5e7eSJeff Biseda p[18] = (gen_number >> 8) & 0xff;
573257ff5e7eSJeff Biseda p[19] = gen_number & 0xff;
5733fcf3ce44SJohn Forte
5734fcf3ce44SJohn Forte return (STMF_SUCCESS);
5735fcf3ce44SJohn Forte }
5736fcf3ce44SJohn Forte
5737fcf3ce44SJohn Forte /*
5738fcf3ce44SJohn Forte * saa is sense key, ASC, ASCQ
5739fcf3ce44SJohn Forte */
5740fcf3ce44SJohn Forte void
stmf_scsilib_send_status(scsi_task_t * task,uint8_t st,uint32_t saa)5741fcf3ce44SJohn Forte stmf_scsilib_send_status(scsi_task_t *task, uint8_t st, uint32_t saa)
5742fcf3ce44SJohn Forte {
5743fcf3ce44SJohn Forte uint8_t sd[18];
5744fcf3ce44SJohn Forte task->task_scsi_status = st;
5745fcf3ce44SJohn Forte if (st == 2) {
5746fcf3ce44SJohn Forte bzero(sd, 18);
5747fcf3ce44SJohn Forte sd[0] = 0x70;
5748fcf3ce44SJohn Forte sd[2] = (saa >> 16) & 0xf;
5749fcf3ce44SJohn Forte sd[7] = 10;
5750fcf3ce44SJohn Forte sd[12] = (saa >> 8) & 0xff;
5751fcf3ce44SJohn Forte sd[13] = saa & 0xff;
5752fcf3ce44SJohn Forte task->task_sense_data = sd;
5753fcf3ce44SJohn Forte task->task_sense_length = 18;
5754fcf3ce44SJohn Forte } else {
5755fcf3ce44SJohn Forte task->task_sense_data = NULL;
5756fcf3ce44SJohn Forte task->task_sense_length = 0;
5757fcf3ce44SJohn Forte }
5758fcf3ce44SJohn Forte (void) stmf_send_scsi_status(task, STMF_IOF_LU_DONE);
5759fcf3ce44SJohn Forte }
5760fcf3ce44SJohn Forte
5761fcf3ce44SJohn 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)5762fcf3ce44SJohn Forte stmf_scsilib_prepare_vpd_page83(scsi_task_t *task, uint8_t *page,
5763fcf3ce44SJohn Forte uint32_t page_len, uint8_t byte0, uint32_t vpd_mask)
5764fcf3ce44SJohn Forte {
5765fcf3ce44SJohn Forte uint8_t *p = NULL;
5766fcf3ce44SJohn Forte uint8_t small_buf[32];
5767fcf3ce44SJohn Forte uint32_t sz = 0;
5768fcf3ce44SJohn Forte uint32_t n = 4;
5769fcf3ce44SJohn Forte uint32_t m = 0;
5770fcf3ce44SJohn Forte uint32_t last_bit = 0;
5771fcf3ce44SJohn Forte
5772fcf3ce44SJohn Forte if (page_len < 4)
5773fcf3ce44SJohn Forte return (0);
5774fcf3ce44SJohn Forte if (page_len > 65535)
5775fcf3ce44SJohn Forte page_len = 65535;
5776fcf3ce44SJohn Forte
5777fcf3ce44SJohn Forte page[0] = byte0;
5778fcf3ce44SJohn Forte page[1] = 0x83;
5779fcf3ce44SJohn Forte
5780fcf3ce44SJohn Forte /* CONSTCOND */
5781fcf3ce44SJohn Forte while (1) {
5782fcf3ce44SJohn Forte m += sz;
5783fcf3ce44SJohn Forte if (sz && (page_len > n)) {
5784fcf3ce44SJohn Forte uint32_t copysz;
5785fcf3ce44SJohn Forte copysz = page_len > (n + sz) ? sz : page_len - n;
5786fcf3ce44SJohn Forte bcopy(p, page + n, copysz);
5787fcf3ce44SJohn Forte n += copysz;
5788fcf3ce44SJohn Forte }
5789fcf3ce44SJohn Forte vpd_mask &= ~last_bit;
5790fcf3ce44SJohn Forte if (vpd_mask == 0)
5791fcf3ce44SJohn Forte break;
5792fcf3ce44SJohn Forte
5793fcf3ce44SJohn Forte if (vpd_mask & STMF_VPD_LU_ID) {
5794fcf3ce44SJohn Forte last_bit = STMF_VPD_LU_ID;
5795fcf3ce44SJohn Forte sz = task->task_lu->lu_id->ident_length + 4;
5796fcf3ce44SJohn Forte p = (uint8_t *)task->task_lu->lu_id;
5797fcf3ce44SJohn Forte continue;
5798fcf3ce44SJohn Forte } else if (vpd_mask & STMF_VPD_TARGET_ID) {
5799fcf3ce44SJohn Forte last_bit = STMF_VPD_TARGET_ID;
5800fcf3ce44SJohn Forte sz = task->task_lport->lport_id->ident_length + 4;
5801fcf3ce44SJohn Forte p = (uint8_t *)task->task_lport->lport_id;
5802fcf3ce44SJohn Forte continue;
5803fcf3ce44SJohn Forte } else if (vpd_mask & STMF_VPD_TP_GROUP) {
580445039663SJohn Forte stmf_i_local_port_t *ilport;
5805fcf3ce44SJohn Forte last_bit = STMF_VPD_TP_GROUP;
5806fcf3ce44SJohn Forte p = small_buf;
5807fcf3ce44SJohn Forte bzero(p, 8);
5808fcf3ce44SJohn Forte p[0] = 1;
5809fcf3ce44SJohn Forte p[1] = 0x15;
5810fcf3ce44SJohn Forte p[3] = 4;
581145039663SJohn Forte ilport = (stmf_i_local_port_t *)
581245039663SJohn Forte task->task_lport->lport_stmf_private;
581394d9b8e1SJohn Forte /*
581494d9b8e1SJohn Forte * If we're in alua mode, group 1 contains all alua
581594d9b8e1SJohn Forte * participating ports and all standby ports
581694d9b8e1SJohn Forte * > 255. Otherwise, if we're in alua mode, any local
581794d9b8e1SJohn Forte * ports (non standby/pppt) are also in group 1 if the
581894d9b8e1SJohn Forte * alua node is 1. Otherwise the group is 0.
581994d9b8e1SJohn Forte */
582094d9b8e1SJohn Forte if ((stmf_state.stmf_alua_state &&
582194d9b8e1SJohn Forte (ilport->ilport_alua || ilport->ilport_standby) &&
582294d9b8e1SJohn Forte ilport->ilport_rtpid > 255) ||
582394d9b8e1SJohn Forte (stmf_state.stmf_alua_node == 1 &&
582494d9b8e1SJohn Forte ilport->ilport_standby != 1)) {
582545039663SJohn Forte p[7] = 1; /* Group 1 */
582645039663SJohn Forte }
5827fcf3ce44SJohn Forte sz = 8;
5828fcf3ce44SJohn Forte continue;
5829fcf3ce44SJohn Forte } else if (vpd_mask & STMF_VPD_RELATIVE_TP_ID) {
5830fcf3ce44SJohn Forte stmf_i_local_port_t *ilport;
5831fcf3ce44SJohn Forte
5832fcf3ce44SJohn Forte last_bit = STMF_VPD_RELATIVE_TP_ID;
5833fcf3ce44SJohn Forte p = small_buf;
5834fcf3ce44SJohn Forte bzero(p, 8);
5835fcf3ce44SJohn Forte p[0] = 1;
5836fcf3ce44SJohn Forte p[1] = 0x14;
5837fcf3ce44SJohn Forte p[3] = 4;
5838fcf3ce44SJohn Forte ilport = (stmf_i_local_port_t *)
5839fcf3ce44SJohn Forte task->task_lport->lport_stmf_private;
5840fcf3ce44SJohn Forte p[6] = (ilport->ilport_rtpid >> 8) & 0xff;
5841fcf3ce44SJohn Forte p[7] = ilport->ilport_rtpid & 0xff;
5842fcf3ce44SJohn Forte sz = 8;
5843fcf3ce44SJohn Forte continue;
5844fcf3ce44SJohn Forte } else {
5845fcf3ce44SJohn Forte cmn_err(CE_WARN, "Invalid vpd_mask");
5846fcf3ce44SJohn Forte break;
5847fcf3ce44SJohn Forte }
5848fcf3ce44SJohn Forte }
5849fcf3ce44SJohn Forte
5850fcf3ce44SJohn Forte page[2] = (m >> 8) & 0xff;
5851fcf3ce44SJohn Forte page[3] = m & 0xff;
5852fcf3ce44SJohn Forte
5853fcf3ce44SJohn Forte return (n);
5854fcf3ce44SJohn Forte }
5855fcf3ce44SJohn Forte
5856fcf3ce44SJohn Forte void
stmf_scsilib_handle_report_tpgs(scsi_task_t * task,stmf_data_buf_t * dbuf)5857fcf3ce44SJohn Forte stmf_scsilib_handle_report_tpgs(scsi_task_t *task, stmf_data_buf_t *dbuf)
5858fcf3ce44SJohn Forte {
5859fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
5860fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
586145039663SJohn Forte stmf_i_lu_t *ilu =
586245039663SJohn Forte (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
5863fcf3ce44SJohn Forte stmf_xfer_data_t *xd;
5864fcf3ce44SJohn Forte uint32_t sz, minsz;
5865fcf3ce44SJohn Forte
5866fcf3ce44SJohn Forte itask->itask_flags |= ITASK_DEFAULT_HANDLING;
5867fcf3ce44SJohn Forte task->task_cmd_xfer_length =
5868fcf3ce44SJohn Forte ((((uint32_t)task->task_cdb[6]) << 24) |
5869fcf3ce44SJohn Forte (((uint32_t)task->task_cdb[7]) << 16) |
5870fcf3ce44SJohn Forte (((uint32_t)task->task_cdb[8]) << 8) |
5871fcf3ce44SJohn Forte ((uint32_t)task->task_cdb[9]));
5872fcf3ce44SJohn Forte
5873fcf3ce44SJohn Forte if (task->task_additional_flags &
5874fcf3ce44SJohn Forte TASK_AF_NO_EXPECTED_XFER_LENGTH) {
5875fcf3ce44SJohn Forte task->task_expected_xfer_length =
5876fcf3ce44SJohn Forte task->task_cmd_xfer_length;
5877fcf3ce44SJohn Forte }
5878fcf3ce44SJohn Forte
5879729dd25cSWayne Ihde if (task->task_cmd_xfer_length == 0) {
5880729dd25cSWayne Ihde stmf_scsilib_send_status(task, STATUS_GOOD, 0);
5881729dd25cSWayne Ihde return;
5882729dd25cSWayne Ihde }
5883729dd25cSWayne Ihde if (task->task_cmd_xfer_length < 4) {
5884fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
5885fcf3ce44SJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
5886fcf3ce44SJohn Forte return;
5887fcf3ce44SJohn Forte }
5888fcf3ce44SJohn Forte
5889fcf3ce44SJohn Forte sz = min(task->task_expected_xfer_length,
5890fcf3ce44SJohn Forte task->task_cmd_xfer_length);
5891fcf3ce44SJohn Forte
589245039663SJohn Forte xd = stmf_prepare_tpgs_data(ilu->ilu_alua);
5893fcf3ce44SJohn Forte
5894fcf3ce44SJohn Forte if (xd == NULL) {
5895fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
5896fcf3ce44SJohn Forte STMF_ALLOC_FAILURE, NULL);
5897fcf3ce44SJohn Forte return;
5898fcf3ce44SJohn Forte }
5899fcf3ce44SJohn Forte
5900fcf3ce44SJohn Forte sz = min(sz, xd->size_left);
5901fcf3ce44SJohn Forte xd->size_left = sz;
5902fcf3ce44SJohn Forte minsz = min(512, sz);
5903fcf3ce44SJohn Forte
5904fcf3ce44SJohn Forte if (dbuf == NULL)
5905fcf3ce44SJohn Forte dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0);
5906fcf3ce44SJohn Forte if (dbuf == NULL) {
5907fcf3ce44SJohn Forte kmem_free(xd, xd->alloc_size);
5908fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
5909fcf3ce44SJohn Forte STMF_ALLOC_FAILURE, NULL);
5910fcf3ce44SJohn Forte return;
5911fcf3ce44SJohn Forte }
5912fcf3ce44SJohn Forte dbuf->db_lu_private = xd;
591391159e90SJohn Forte stmf_xd_to_dbuf(dbuf, 1);
5914fcf3ce44SJohn Forte
5915fcf3ce44SJohn Forte dbuf->db_flags = DB_DIRECTION_TO_RPORT;
5916fcf3ce44SJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
5917fcf3ce44SJohn Forte
5918fcf3ce44SJohn Forte }
5919fcf3ce44SJohn Forte
5920fcf3ce44SJohn Forte void
stmf_scsilib_handle_task_mgmt(scsi_task_t * task)5921fcf3ce44SJohn Forte stmf_scsilib_handle_task_mgmt(scsi_task_t *task)
5922fcf3ce44SJohn Forte {
592345039663SJohn Forte
5924fcf3ce44SJohn Forte switch (task->task_mgmt_function) {
5925fcf3ce44SJohn Forte /*
5926fcf3ce44SJohn Forte * For now we will abort all I/Os on the LU in case of ABORT_TASK_SET
5927fcf3ce44SJohn Forte * and ABORT_TASK. But unlike LUN_RESET we will not reset LU state
5928fcf3ce44SJohn Forte * in these cases. This needs to be changed to abort only the required
5929fcf3ce44SJohn Forte * set.
5930fcf3ce44SJohn Forte */
5931fcf3ce44SJohn Forte case TM_ABORT_TASK:
5932fcf3ce44SJohn Forte case TM_ABORT_TASK_SET:
5933fcf3ce44SJohn Forte case TM_CLEAR_TASK_SET:
5934fcf3ce44SJohn Forte case TM_LUN_RESET:
5935fcf3ce44SJohn Forte stmf_handle_lun_reset(task);
593645039663SJohn Forte /* issue the reset to the proxy node as well */
59377beff157SJohn Forte if (stmf_state.stmf_alua_state == 1) {
593845039663SJohn Forte (void) stmf_proxy_scsi_cmd(task, NULL);
59397beff157SJohn Forte }
5940fcf3ce44SJohn Forte return;
5941fcf3ce44SJohn Forte case TM_TARGET_RESET:
5942fcf3ce44SJohn Forte case TM_TARGET_COLD_RESET:
5943fcf3ce44SJohn Forte case TM_TARGET_WARM_RESET:
5944fcf3ce44SJohn Forte stmf_handle_target_reset(task);
5945fcf3ce44SJohn Forte return;
5946fcf3ce44SJohn Forte default:
5947fcf3ce44SJohn Forte /* We dont support this task mgmt function */
5948fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
5949fcf3ce44SJohn Forte STMF_SAA_INVALID_FIELD_IN_CMD_IU);
5950fcf3ce44SJohn Forte return;
5951fcf3ce44SJohn Forte }
5952fcf3ce44SJohn Forte }
5953fcf3ce44SJohn Forte
5954fcf3ce44SJohn Forte void
stmf_handle_lun_reset(scsi_task_t * task)5955fcf3ce44SJohn Forte stmf_handle_lun_reset(scsi_task_t *task)
5956fcf3ce44SJohn Forte {
5957fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask;
5958fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
5959fcf3ce44SJohn Forte
5960fcf3ce44SJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
5961fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
5962fcf3ce44SJohn Forte
5963fcf3ce44SJohn Forte /*
5964fcf3ce44SJohn Forte * To sync with target reset, grab this lock. The LU is not going
5965fcf3ce44SJohn Forte * anywhere as there is atleast one task pending (this task).
5966fcf3ce44SJohn Forte */
5967fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
5968fcf3ce44SJohn Forte
5969fcf3ce44SJohn Forte if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
5970fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5971fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
5972fcf3ce44SJohn Forte STMF_SAA_OPERATION_IN_PROGRESS);
5973fcf3ce44SJohn Forte return;
5974fcf3ce44SJohn Forte }
5975fcf3ce44SJohn Forte atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE);
5976fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
5977fcf3ce44SJohn Forte
5978fcf3ce44SJohn Forte /*
5979fcf3ce44SJohn Forte * Mark this task as the one causing LU reset so that we know who
5980fcf3ce44SJohn Forte * was responsible for setting the ILU_RESET_ACTIVE. In case this
5981fcf3ce44SJohn Forte * task itself gets aborted, we will clear ILU_RESET_ACTIVE.
5982fcf3ce44SJohn Forte */
5983fcf3ce44SJohn Forte itask->itask_flags |= ITASK_DEFAULT_HANDLING | ITASK_CAUSING_LU_RESET;
5984fcf3ce44SJohn Forte
5985fcf3ce44SJohn Forte /* Initiatiate abort on all commands on this LU except this one */
5986fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED, task->task_lu);
5987fcf3ce44SJohn Forte
5988fcf3ce44SJohn Forte /* Start polling on this task */
5989fcf3ce44SJohn Forte if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
5990fcf3ce44SJohn Forte != STMF_SUCCESS) {
5991fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE,
5992fcf3ce44SJohn Forte NULL);
5993fcf3ce44SJohn Forte return;
5994fcf3ce44SJohn Forte }
5995fcf3ce44SJohn Forte }
5996fcf3ce44SJohn Forte
5997fcf3ce44SJohn Forte void
stmf_handle_target_reset(scsi_task_t * task)5998fcf3ce44SJohn Forte stmf_handle_target_reset(scsi_task_t *task)
5999fcf3ce44SJohn Forte {
6000fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask;
6001fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
6002fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
6003fcf3ce44SJohn Forte stmf_lun_map_t *lm;
6004fcf3ce44SJohn Forte stmf_lun_map_ent_t *lm_ent;
6005fcf3ce44SJohn Forte int i, lf;
6006fcf3ce44SJohn Forte
6007fcf3ce44SJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
6008fcf3ce44SJohn Forte iss = (stmf_i_scsi_session_t *)task->task_session->ss_stmf_private;
6009fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
6010fcf3ce44SJohn Forte
6011fcf3ce44SJohn Forte /*
6012fcf3ce44SJohn Forte * To sync with LUN reset, grab this lock. The session is not going
6013fcf3ce44SJohn Forte * anywhere as there is atleast one task pending (this task).
6014fcf3ce44SJohn Forte */
6015fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
6016d6b3018dSSumit Gupta
6017d6b3018dSSumit Gupta /* Grab the session lock as a writer to prevent any changes in it */
6018d6b3018dSSumit Gupta rw_enter(iss->iss_lockp, RW_WRITER);
6019d6b3018dSSumit Gupta
6020fcf3ce44SJohn Forte if (iss->iss_flags & ISS_RESET_ACTIVE) {
6021fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
6022d6b3018dSSumit Gupta mutex_exit(&stmf_state.stmf_lock);
6023fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
6024fcf3ce44SJohn Forte STMF_SAA_OPERATION_IN_PROGRESS);
6025fcf3ce44SJohn Forte return;
6026fcf3ce44SJohn Forte }
6027fcf3ce44SJohn Forte atomic_or_32(&iss->iss_flags, ISS_RESET_ACTIVE);
6028fcf3ce44SJohn Forte
6029fcf3ce44SJohn Forte /*
6030fcf3ce44SJohn Forte * Now go through each LUN in this session and make sure all of them
6031fcf3ce44SJohn Forte * can be reset.
6032fcf3ce44SJohn Forte */
6033fcf3ce44SJohn Forte lm = iss->iss_sm;
6034fcf3ce44SJohn Forte for (i = 0, lf = 0; i < lm->lm_nentries; i++) {
6035fcf3ce44SJohn Forte if (lm->lm_plus[i] == NULL)
6036fcf3ce44SJohn Forte continue;
6037fcf3ce44SJohn Forte lf++;
6038fcf3ce44SJohn Forte lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6039fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private);
6040fcf3ce44SJohn Forte if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
6041fcf3ce44SJohn Forte atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
6042fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
6043d6b3018dSSumit Gupta mutex_exit(&stmf_state.stmf_lock);
6044fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
6045fcf3ce44SJohn Forte STMF_SAA_OPERATION_IN_PROGRESS);
6046fcf3ce44SJohn Forte return;
6047fcf3ce44SJohn Forte }
6048fcf3ce44SJohn Forte }
6049fcf3ce44SJohn Forte if (lf == 0) {
6050fcf3ce44SJohn Forte /* No luns in this session */
6051fcf3ce44SJohn Forte atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
6052fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
6053d6b3018dSSumit Gupta mutex_exit(&stmf_state.stmf_lock);
6054fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6055fcf3ce44SJohn Forte return;
6056fcf3ce44SJohn Forte }
6057fcf3ce44SJohn Forte
6058fcf3ce44SJohn Forte /* ok, start the damage */
6059fcf3ce44SJohn Forte itask->itask_flags |= ITASK_DEFAULT_HANDLING |
6060fcf3ce44SJohn Forte ITASK_CAUSING_TARGET_RESET;
6061fcf3ce44SJohn Forte for (i = 0; i < lm->lm_nentries; i++) {
6062fcf3ce44SJohn Forte if (lm->lm_plus[i] == NULL)
6063fcf3ce44SJohn Forte continue;
6064fcf3ce44SJohn Forte lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6065fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private);
6066fcf3ce44SJohn Forte atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE);
6067fcf3ce44SJohn Forte }
6068fcf3ce44SJohn Forte
6069fcf3ce44SJohn Forte for (i = 0; i < lm->lm_nentries; i++) {
6070fcf3ce44SJohn Forte if (lm->lm_plus[i] == NULL)
6071fcf3ce44SJohn Forte continue;
6072fcf3ce44SJohn Forte lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6073fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED,
6074fcf3ce44SJohn Forte lm_ent->ent_lu);
6075fcf3ce44SJohn Forte }
6076fcf3ce44SJohn Forte
6077780c822cStim szeto rw_exit(iss->iss_lockp);
6078780c822cStim szeto mutex_exit(&stmf_state.stmf_lock);
6079780c822cStim szeto
6080fcf3ce44SJohn Forte /* Start polling on this task */
6081fcf3ce44SJohn Forte if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
6082fcf3ce44SJohn Forte != STMF_SUCCESS) {
6083fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE,
6084fcf3ce44SJohn Forte NULL);
6085fcf3ce44SJohn Forte return;
6086fcf3ce44SJohn Forte }
6087fcf3ce44SJohn Forte }
6088fcf3ce44SJohn Forte
6089fcf3ce44SJohn Forte int
stmf_handle_cmd_during_ic(stmf_i_scsi_task_t * itask)6090fcf3ce44SJohn Forte stmf_handle_cmd_during_ic(stmf_i_scsi_task_t *itask)
6091fcf3ce44SJohn Forte {
6092fcf3ce44SJohn Forte scsi_task_t *task = itask->itask_task;
6093fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
6094fcf3ce44SJohn Forte task->task_session->ss_stmf_private;
6095fcf3ce44SJohn Forte
6096fcf3ce44SJohn Forte rw_enter(iss->iss_lockp, RW_WRITER);
6097fcf3ce44SJohn Forte if (((iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) == 0) ||
6098fcf3ce44SJohn Forte (task->task_cdb[0] == SCMD_INQUIRY)) {
6099fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
6100fcf3ce44SJohn Forte return (0);
6101fcf3ce44SJohn Forte }
6102fcf3ce44SJohn Forte atomic_and_32(&iss->iss_flags,
6103fcf3ce44SJohn Forte ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS));
6104fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
6105fcf3ce44SJohn Forte
6106fcf3ce44SJohn Forte if (task->task_cdb[0] == SCMD_REPORT_LUNS) {
6107fcf3ce44SJohn Forte return (0);
6108fcf3ce44SJohn Forte }
6109fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
6110fcf3ce44SJohn Forte STMF_SAA_REPORT_LUN_DATA_HAS_CHANGED);
6111fcf3ce44SJohn Forte return (1);
6112fcf3ce44SJohn Forte }
6113fcf3ce44SJohn Forte
6114fcf3ce44SJohn Forte void
stmf_worker_init()6115fcf3ce44SJohn Forte stmf_worker_init()
6116fcf3ce44SJohn Forte {
6117fcf3ce44SJohn Forte uint32_t i;
6118fcf3ce44SJohn Forte
6119fcf3ce44SJohn Forte /* Make local copy of global tunables */
6120fcf3ce44SJohn Forte stmf_i_max_nworkers = stmf_max_nworkers;
6121fcf3ce44SJohn Forte stmf_i_min_nworkers = stmf_min_nworkers;
6122fcf3ce44SJohn Forte
6123fcf3ce44SJohn Forte ASSERT(stmf_workers == NULL);
6124fcf3ce44SJohn Forte if (stmf_i_min_nworkers < 4) {
6125fcf3ce44SJohn Forte stmf_i_min_nworkers = 4;
6126fcf3ce44SJohn Forte }
6127fcf3ce44SJohn Forte if (stmf_i_max_nworkers < stmf_i_min_nworkers) {
6128fcf3ce44SJohn Forte stmf_i_max_nworkers = stmf_i_min_nworkers;
6129fcf3ce44SJohn Forte }
6130fcf3ce44SJohn Forte stmf_workers = (stmf_worker_t *)kmem_zalloc(
6131fcf3ce44SJohn Forte sizeof (stmf_worker_t) * stmf_i_max_nworkers, KM_SLEEP);
6132fcf3ce44SJohn Forte for (i = 0; i < stmf_i_max_nworkers; i++) {
6133fcf3ce44SJohn Forte stmf_worker_t *w = &stmf_workers[i];
6134fcf3ce44SJohn Forte mutex_init(&w->worker_lock, NULL, MUTEX_DRIVER, NULL);
6135fcf3ce44SJohn Forte cv_init(&w->worker_cv, NULL, CV_DRIVER, NULL);
6136fcf3ce44SJohn Forte }
6137fcf3ce44SJohn Forte stmf_worker_mgmt_delay = drv_usectohz(20 * 1000);
6138fcf3ce44SJohn Forte stmf_workers_state = STMF_WORKERS_ENABLED;
6139fcf3ce44SJohn Forte
6140fcf3ce44SJohn Forte /* Workers will be started by stmf_worker_mgmt() */
6141fcf3ce44SJohn Forte
6142fcf3ce44SJohn Forte /* Lets wait for atleast one worker to start */
6143fcf3ce44SJohn Forte while (stmf_nworkers_cur == 0)
6144fcf3ce44SJohn Forte delay(drv_usectohz(20 * 1000));
6145fcf3ce44SJohn Forte stmf_worker_mgmt_delay = drv_usectohz(3 * 1000 * 1000);
6146fcf3ce44SJohn Forte }
6147fcf3ce44SJohn Forte
6148fcf3ce44SJohn Forte stmf_status_t
stmf_worker_fini()6149fcf3ce44SJohn Forte stmf_worker_fini()
6150fcf3ce44SJohn Forte {
6151fcf3ce44SJohn Forte int i;
6152fcf3ce44SJohn Forte clock_t sb;
6153fcf3ce44SJohn Forte
6154fcf3ce44SJohn Forte if (stmf_workers_state == STMF_WORKERS_DISABLED)
6155fcf3ce44SJohn Forte return (STMF_SUCCESS);
6156fcf3ce44SJohn Forte ASSERT(stmf_workers);
6157fcf3ce44SJohn Forte stmf_workers_state = STMF_WORKERS_DISABLED;
6158fcf3ce44SJohn Forte stmf_worker_mgmt_delay = drv_usectohz(20 * 1000);
6159fcf3ce44SJohn Forte cv_signal(&stmf_state.stmf_cv);
6160fcf3ce44SJohn Forte
6161fcf3ce44SJohn Forte sb = ddi_get_lbolt() + drv_usectohz(10 * 1000 * 1000);
6162fcf3ce44SJohn Forte /* Wait for all the threads to die */
6163fcf3ce44SJohn Forte while (stmf_nworkers_cur != 0) {
6164fcf3ce44SJohn Forte if (ddi_get_lbolt() > sb) {
6165fcf3ce44SJohn Forte stmf_workers_state = STMF_WORKERS_ENABLED;
6166fcf3ce44SJohn Forte return (STMF_BUSY);
6167fcf3ce44SJohn Forte }
6168fcf3ce44SJohn Forte delay(drv_usectohz(100 * 1000));
6169fcf3ce44SJohn Forte }
6170fcf3ce44SJohn Forte for (i = 0; i < stmf_i_max_nworkers; i++) {
6171fcf3ce44SJohn Forte stmf_worker_t *w = &stmf_workers[i];
6172fcf3ce44SJohn Forte mutex_destroy(&w->worker_lock);
6173fcf3ce44SJohn Forte cv_destroy(&w->worker_cv);
6174fcf3ce44SJohn Forte }
6175fcf3ce44SJohn Forte kmem_free(stmf_workers, sizeof (stmf_worker_t) * stmf_i_max_nworkers);
6176fcf3ce44SJohn Forte stmf_workers = NULL;
6177fcf3ce44SJohn Forte
6178fcf3ce44SJohn Forte return (STMF_SUCCESS);
6179fcf3ce44SJohn Forte }
6180fcf3ce44SJohn Forte
6181fcf3ce44SJohn Forte void
stmf_worker_task(void * arg)6182fcf3ce44SJohn Forte stmf_worker_task(void *arg)
6183fcf3ce44SJohn Forte {
6184fcf3ce44SJohn Forte stmf_worker_t *w;
6185fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
6186fcf3ce44SJohn Forte scsi_task_t *task;
6187fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask;
6188fcf3ce44SJohn Forte stmf_data_buf_t *dbuf;
6189fcf3ce44SJohn Forte stmf_lu_t *lu;
6190fcf3ce44SJohn Forte clock_t wait_timer = 0;
6191d3d50737SRafael Vanoni clock_t wait_ticks, wait_delta = 0;
6192fcf3ce44SJohn Forte uint32_t old, new;
6193fcf3ce44SJohn Forte uint8_t curcmd;
6194fcf3ce44SJohn Forte uint8_t abort_free;
6195fcf3ce44SJohn Forte uint8_t wait_queue;
6196fcf3ce44SJohn Forte uint8_t dec_qdepth;
6197fcf3ce44SJohn Forte
6198fcf3ce44SJohn Forte w = (stmf_worker_t *)arg;
6199fcf3ce44SJohn Forte wait_ticks = drv_usectohz(10000);
6200fcf3ce44SJohn Forte
6201427fcaf8Stim szeto DTRACE_PROBE1(worker__create, stmf_worker_t, w);
6202fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
6203fcf3ce44SJohn Forte w->worker_flags |= STMF_WORKER_STARTED | STMF_WORKER_ACTIVE;
6204fcf3ce44SJohn Forte stmf_worker_loop:;
6205fcf3ce44SJohn Forte if ((w->worker_ref_count == 0) &&
6206fcf3ce44SJohn Forte (w->worker_flags & STMF_WORKER_TERMINATE)) {
6207fcf3ce44SJohn Forte w->worker_flags &= ~(STMF_WORKER_STARTED |
6208fcf3ce44SJohn Forte STMF_WORKER_ACTIVE | STMF_WORKER_TERMINATE);
6209fcf3ce44SJohn Forte w->worker_tid = NULL;
6210fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
6211427fcaf8Stim szeto DTRACE_PROBE1(worker__destroy, stmf_worker_t, w);
6212fcf3ce44SJohn Forte thread_exit();
6213fcf3ce44SJohn Forte }
6214fcf3ce44SJohn Forte /* CONSTCOND */
6215fcf3ce44SJohn Forte while (1) {
6216fcf3ce44SJohn Forte dec_qdepth = 0;
6217fcf3ce44SJohn Forte if (wait_timer && (ddi_get_lbolt() >= wait_timer)) {
6218fcf3ce44SJohn Forte wait_timer = 0;
6219d3d50737SRafael Vanoni wait_delta = 0;
6220d6b3018dSSumit Gupta if (w->worker_wait_head) {
6221d6b3018dSSumit Gupta ASSERT(w->worker_wait_tail);
6222fcf3ce44SJohn Forte if (w->worker_task_head == NULL)
6223d6b3018dSSumit Gupta w->worker_task_head =
6224d6b3018dSSumit Gupta w->worker_wait_head;
6225fcf3ce44SJohn Forte else
6226fcf3ce44SJohn Forte w->worker_task_tail->itask_worker_next =
6227fcf3ce44SJohn Forte w->worker_wait_head;
6228fcf3ce44SJohn Forte w->worker_task_tail = w->worker_wait_tail;
6229d6b3018dSSumit Gupta w->worker_wait_head = w->worker_wait_tail =
6230d6b3018dSSumit Gupta NULL;
6231d6b3018dSSumit Gupta }
6232fcf3ce44SJohn Forte }
6233fcf3ce44SJohn Forte if ((itask = w->worker_task_head) == NULL) {
6234fcf3ce44SJohn Forte break;
6235fcf3ce44SJohn Forte }
6236fcf3ce44SJohn Forte task = itask->itask_task;
6237427fcaf8Stim szeto DTRACE_PROBE2(worker__active, stmf_worker_t, w,
6238427fcaf8Stim szeto scsi_task_t *, task);
6239fcf3ce44SJohn Forte w->worker_task_head = itask->itask_worker_next;
6240fcf3ce44SJohn Forte if (w->worker_task_head == NULL)
6241fcf3ce44SJohn Forte w->worker_task_tail = NULL;
6242fcf3ce44SJohn Forte
6243fcf3ce44SJohn Forte wait_queue = 0;
6244fcf3ce44SJohn Forte abort_free = 0;
6245fcf3ce44SJohn Forte if (itask->itask_ncmds > 0) {
6246fcf3ce44SJohn Forte curcmd = itask->itask_cmd_stack[itask->itask_ncmds - 1];
6247fcf3ce44SJohn Forte } else {
6248fcf3ce44SJohn Forte ASSERT(itask->itask_flags & ITASK_BEING_ABORTED);
6249fcf3ce44SJohn Forte }
6250fcf3ce44SJohn Forte do {
6251fcf3ce44SJohn Forte old = itask->itask_flags;
6252fcf3ce44SJohn Forte if (old & ITASK_BEING_ABORTED) {
6253fcf3ce44SJohn Forte itask->itask_ncmds = 1;
6254fcf3ce44SJohn Forte curcmd = itask->itask_cmd_stack[0] =
6255fcf3ce44SJohn Forte ITASK_CMD_ABORT;
6256fcf3ce44SJohn Forte goto out_itask_flag_loop;
6257fcf3ce44SJohn Forte } else if ((curcmd & ITASK_CMD_MASK) ==
6258fcf3ce44SJohn Forte ITASK_CMD_NEW_TASK) {
6259554c2b16Stim szeto /*
6260554c2b16Stim szeto * set ITASK_KSTAT_IN_RUNQ, this flag
6261554c2b16Stim szeto * will not reset until task completed
6262554c2b16Stim szeto */
6263554c2b16Stim szeto new = old | ITASK_KNOWN_TO_LU |
6264554c2b16Stim szeto ITASK_KSTAT_IN_RUNQ;
6265fcf3ce44SJohn Forte } else {
6266fcf3ce44SJohn Forte goto out_itask_flag_loop;
6267fcf3ce44SJohn Forte }
6268fcf3ce44SJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
6269fcf3ce44SJohn Forte
6270fcf3ce44SJohn Forte out_itask_flag_loop:
6271fcf3ce44SJohn Forte
6272fcf3ce44SJohn Forte /*
6273fcf3ce44SJohn Forte * Decide if this task needs to go to a queue and/or if
6274fcf3ce44SJohn Forte * we can decrement the itask_cmd_stack.
6275fcf3ce44SJohn Forte */
6276fcf3ce44SJohn Forte if (curcmd == ITASK_CMD_ABORT) {
6277fcf3ce44SJohn Forte if (itask->itask_flags & (ITASK_KNOWN_TO_LU |
6278fcf3ce44SJohn Forte ITASK_KNOWN_TO_TGT_PORT)) {
6279fcf3ce44SJohn Forte wait_queue = 1;
6280fcf3ce44SJohn Forte } else {
6281fcf3ce44SJohn Forte abort_free = 1;
6282fcf3ce44SJohn Forte }
6283fcf3ce44SJohn Forte } else if ((curcmd & ITASK_CMD_POLL) &&
6284fcf3ce44SJohn Forte (itask->itask_poll_timeout > ddi_get_lbolt())) {
6285fcf3ce44SJohn Forte wait_queue = 1;
6286fcf3ce44SJohn Forte }
6287fcf3ce44SJohn Forte
6288fcf3ce44SJohn Forte if (wait_queue) {
6289fcf3ce44SJohn Forte itask->itask_worker_next = NULL;
6290fcf3ce44SJohn Forte if (w->worker_wait_tail) {
6291fcf3ce44SJohn Forte w->worker_wait_tail->itask_worker_next = itask;
6292fcf3ce44SJohn Forte } else {
6293fcf3ce44SJohn Forte w->worker_wait_head = itask;
6294fcf3ce44SJohn Forte }
6295fcf3ce44SJohn Forte w->worker_wait_tail = itask;
6296fcf3ce44SJohn Forte if (wait_timer == 0) {
6297fcf3ce44SJohn Forte wait_timer = ddi_get_lbolt() + wait_ticks;
6298d3d50737SRafael Vanoni wait_delta = wait_ticks;
6299fcf3ce44SJohn Forte }
6300fcf3ce44SJohn Forte } else if ((--(itask->itask_ncmds)) != 0) {
6301fcf3ce44SJohn Forte itask->itask_worker_next = NULL;
6302fcf3ce44SJohn Forte if (w->worker_task_tail) {
6303fcf3ce44SJohn Forte w->worker_task_tail->itask_worker_next = itask;
6304fcf3ce44SJohn Forte } else {
6305fcf3ce44SJohn Forte w->worker_task_head = itask;
6306fcf3ce44SJohn Forte }
6307fcf3ce44SJohn Forte w->worker_task_tail = itask;
6308fcf3ce44SJohn Forte } else {
6309fcf3ce44SJohn Forte atomic_and_32(&itask->itask_flags,
6310fcf3ce44SJohn Forte ~ITASK_IN_WORKER_QUEUE);
6311fcf3ce44SJohn Forte /*
6312fcf3ce44SJohn Forte * This is where the queue depth should go down by
6313fcf3ce44SJohn Forte * one but we delay that on purpose to account for
6314fcf3ce44SJohn Forte * the call into the provider. The actual decrement
6315fcf3ce44SJohn Forte * happens after the worker has done its job.
6316fcf3ce44SJohn Forte */
6317fcf3ce44SJohn Forte dec_qdepth = 1;
6318427fcaf8Stim szeto itask->itask_waitq_time +=
6319427fcaf8Stim szeto gethrtime() - itask->itask_waitq_enter_timestamp;
6320fcf3ce44SJohn Forte }
6321fcf3ce44SJohn Forte
6322fcf3ce44SJohn Forte /* We made it here means we are going to call LU */
6323fcf3ce44SJohn Forte if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0)
6324fcf3ce44SJohn Forte lu = task->task_lu;
6325fcf3ce44SJohn Forte else
6326fcf3ce44SJohn Forte lu = dlun0;
6327fcf3ce44SJohn Forte dbuf = itask->itask_dbufs[ITASK_CMD_BUF_NDX(curcmd)];
6328fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
6329fcf3ce44SJohn Forte curcmd &= ITASK_CMD_MASK;
633040c3e8ffSJohn Forte stmf_task_audit(itask, TE_PROCESS_CMD, curcmd, dbuf);
6331fcf3ce44SJohn Forte switch (curcmd) {
6332fcf3ce44SJohn Forte case ITASK_CMD_NEW_TASK:
6333fcf3ce44SJohn Forte iss = (stmf_i_scsi_session_t *)
6334fcf3ce44SJohn Forte task->task_session->ss_stmf_private;
6335427fcaf8Stim szeto stmf_itl_lu_new_task(itask);
6336fcf3ce44SJohn Forte if (iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) {
6337fcf3ce44SJohn Forte if (stmf_handle_cmd_during_ic(itask))
6338fcf3ce44SJohn Forte break;
6339fcf3ce44SJohn Forte }
6340fcf3ce44SJohn Forte #ifdef DEBUG
6341fcf3ce44SJohn Forte if (stmf_drop_task_counter > 0) {
6342*9c68c052SJosef 'Jeff' Sipek if (atomic_dec_32_nv(&stmf_drop_task_counter)
6343*9c68c052SJosef 'Jeff' Sipek == 1)
6344fcf3ce44SJohn Forte break;
6345fcf3ce44SJohn Forte }
6346fcf3ce44SJohn Forte #endif
6347e17f3b22Stim szeto DTRACE_PROBE1(scsi__task__start, scsi_task_t *, task);
6348fcf3ce44SJohn Forte lu->lu_new_task(task, dbuf);
6349fcf3ce44SJohn Forte break;
6350fcf3ce44SJohn Forte case ITASK_CMD_DATA_XFER_DONE:
6351fcf3ce44SJohn Forte lu->lu_dbuf_xfer_done(task, dbuf);
6352fcf3ce44SJohn Forte break;
6353fcf3ce44SJohn Forte case ITASK_CMD_STATUS_DONE:
6354fcf3ce44SJohn Forte lu->lu_send_status_done(task);
6355fcf3ce44SJohn Forte break;
6356fcf3ce44SJohn Forte case ITASK_CMD_ABORT:
6357fcf3ce44SJohn Forte if (abort_free) {
6358fcf3ce44SJohn Forte stmf_task_free(task);
6359fcf3ce44SJohn Forte } else {
6360fcf3ce44SJohn Forte stmf_do_task_abort(task);
6361fcf3ce44SJohn Forte }
6362fcf3ce44SJohn Forte break;
6363fcf3ce44SJohn Forte case ITASK_CMD_POLL_LU:
6364fcf3ce44SJohn Forte if (!wait_queue) {
6365fcf3ce44SJohn Forte lu->lu_task_poll(task);
6366fcf3ce44SJohn Forte }
6367fcf3ce44SJohn Forte break;
6368fcf3ce44SJohn Forte case ITASK_CMD_POLL_LPORT:
6369fcf3ce44SJohn Forte if (!wait_queue)
6370fcf3ce44SJohn Forte task->task_lport->lport_task_poll(task);
6371fcf3ce44SJohn Forte break;
6372fcf3ce44SJohn Forte case ITASK_CMD_SEND_STATUS:
6373fcf3ce44SJohn Forte /* case ITASK_CMD_XFER_DATA: */
6374fcf3ce44SJohn Forte break;
6375fcf3ce44SJohn Forte }
6376fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
6377fcf3ce44SJohn Forte if (dec_qdepth) {
6378fcf3ce44SJohn Forte w->worker_queue_depth--;
6379fcf3ce44SJohn Forte }
6380fcf3ce44SJohn Forte }
6381fcf3ce44SJohn Forte if ((w->worker_flags & STMF_WORKER_TERMINATE) && (wait_timer == 0)) {
6382fcf3ce44SJohn Forte if (w->worker_ref_count == 0)
6383fcf3ce44SJohn Forte goto stmf_worker_loop;
6384d3d50737SRafael Vanoni else {
6385fcf3ce44SJohn Forte wait_timer = ddi_get_lbolt() + 1;
6386d3d50737SRafael Vanoni wait_delta = 1;
6387d3d50737SRafael Vanoni }
6388fcf3ce44SJohn Forte }
6389fcf3ce44SJohn Forte w->worker_flags &= ~STMF_WORKER_ACTIVE;
6390fcf3ce44SJohn Forte if (wait_timer) {
6391427fcaf8Stim szeto DTRACE_PROBE1(worker__timed__sleep, stmf_worker_t, w);
6392d3d50737SRafael Vanoni (void) cv_reltimedwait(&w->worker_cv, &w->worker_lock,
6393d3d50737SRafael Vanoni wait_delta, TR_CLOCK_TICK);
6394fcf3ce44SJohn Forte } else {
6395427fcaf8Stim szeto DTRACE_PROBE1(worker__sleep, stmf_worker_t, w);
6396fcf3ce44SJohn Forte cv_wait(&w->worker_cv, &w->worker_lock);
6397fcf3ce44SJohn Forte }
6398427fcaf8Stim szeto DTRACE_PROBE1(worker__wakeup, stmf_worker_t, w);
6399fcf3ce44SJohn Forte w->worker_flags |= STMF_WORKER_ACTIVE;
6400fcf3ce44SJohn Forte goto stmf_worker_loop;
6401fcf3ce44SJohn Forte }
6402fcf3ce44SJohn Forte
6403fcf3ce44SJohn Forte void
stmf_worker_mgmt()6404fcf3ce44SJohn Forte stmf_worker_mgmt()
6405fcf3ce44SJohn Forte {
6406fcf3ce44SJohn Forte int i;
6407fcf3ce44SJohn Forte int workers_needed;
6408fcf3ce44SJohn Forte uint32_t qd;
6409fcf3ce44SJohn Forte clock_t tps, d = 0;
6410fcf3ce44SJohn Forte uint32_t cur_max_ntasks = 0;
6411fcf3ce44SJohn Forte stmf_worker_t *w;
6412fcf3ce44SJohn Forte
6413fcf3ce44SJohn Forte /* Check if we are trying to increase the # of threads */
6414fcf3ce44SJohn Forte for (i = stmf_nworkers_cur; i < stmf_nworkers_needed; i++) {
6415fcf3ce44SJohn Forte if (stmf_workers[i].worker_flags & STMF_WORKER_STARTED) {
6416fcf3ce44SJohn Forte stmf_nworkers_cur++;
6417fcf3ce44SJohn Forte stmf_nworkers_accepting_cmds++;
6418fcf3ce44SJohn Forte } else {
6419fcf3ce44SJohn Forte /* Wait for transition to complete */
6420fcf3ce44SJohn Forte return;
6421fcf3ce44SJohn Forte }
6422fcf3ce44SJohn Forte }
6423fcf3ce44SJohn Forte /* Check if we are trying to decrease the # of workers */
6424fcf3ce44SJohn Forte for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) {
6425fcf3ce44SJohn Forte if ((stmf_workers[i].worker_flags & STMF_WORKER_STARTED) == 0) {
6426fcf3ce44SJohn Forte stmf_nworkers_cur--;
6427fcf3ce44SJohn Forte /*
6428fcf3ce44SJohn Forte * stmf_nworkers_accepting_cmds has already been
6429fcf3ce44SJohn Forte * updated by the request to reduce the # of workers.
6430fcf3ce44SJohn Forte */
6431fcf3ce44SJohn Forte } else {
6432fcf3ce44SJohn Forte /* Wait for transition to complete */
6433fcf3ce44SJohn Forte return;
6434fcf3ce44SJohn Forte }
6435fcf3ce44SJohn Forte }
6436fcf3ce44SJohn Forte /* Check if we are being asked to quit */
6437fcf3ce44SJohn Forte if (stmf_workers_state != STMF_WORKERS_ENABLED) {
6438fcf3ce44SJohn Forte if (stmf_nworkers_cur) {
6439fcf3ce44SJohn Forte workers_needed = 0;
6440fcf3ce44SJohn Forte goto worker_mgmt_trigger_change;
6441fcf3ce44SJohn Forte }
6442fcf3ce44SJohn Forte return;
6443fcf3ce44SJohn Forte }
6444fcf3ce44SJohn Forte /* Check if we are starting */
6445fcf3ce44SJohn Forte if (stmf_nworkers_cur < stmf_i_min_nworkers) {
6446fcf3ce44SJohn Forte workers_needed = stmf_i_min_nworkers;
6447fcf3ce44SJohn Forte goto worker_mgmt_trigger_change;
6448fcf3ce44SJohn Forte }
6449fcf3ce44SJohn Forte
6450fcf3ce44SJohn Forte tps = drv_usectohz(1 * 1000 * 1000);
6451fcf3ce44SJohn Forte if ((stmf_wm_last != 0) &&
6452fcf3ce44SJohn Forte ((d = ddi_get_lbolt() - stmf_wm_last) > tps)) {
6453fcf3ce44SJohn Forte qd = 0;
6454fcf3ce44SJohn Forte for (i = 0; i < stmf_nworkers_accepting_cmds; i++) {
6455fcf3ce44SJohn Forte qd += stmf_workers[i].worker_max_qdepth_pu;
6456fcf3ce44SJohn Forte stmf_workers[i].worker_max_qdepth_pu = 0;
6457fcf3ce44SJohn Forte if (stmf_workers[i].worker_max_sys_qdepth_pu >
6458fcf3ce44SJohn Forte cur_max_ntasks) {
6459fcf3ce44SJohn Forte cur_max_ntasks =
6460fcf3ce44SJohn Forte stmf_workers[i].worker_max_sys_qdepth_pu;
6461fcf3ce44SJohn Forte }
6462fcf3ce44SJohn Forte stmf_workers[i].worker_max_sys_qdepth_pu = 0;
6463fcf3ce44SJohn Forte }
6464fcf3ce44SJohn Forte }
6465fcf3ce44SJohn Forte stmf_wm_last = ddi_get_lbolt();
6466fcf3ce44SJohn Forte if (d <= tps) {
6467fcf3ce44SJohn Forte /* still ramping up */
6468fcf3ce44SJohn Forte return;
6469fcf3ce44SJohn Forte }
6470fcf3ce44SJohn Forte /* max qdepth cannot be more than max tasks */
6471fcf3ce44SJohn Forte if (qd > cur_max_ntasks)
6472fcf3ce44SJohn Forte qd = cur_max_ntasks;
6473fcf3ce44SJohn Forte
6474fcf3ce44SJohn Forte /* See if we have more workers */
6475fcf3ce44SJohn Forte if (qd < stmf_nworkers_accepting_cmds) {
6476fcf3ce44SJohn Forte /*
6477fcf3ce44SJohn Forte * Since we dont reduce the worker count right away, monitor
6478fcf3ce44SJohn Forte * the highest load during the scale_down_delay.
6479fcf3ce44SJohn Forte */
6480fcf3ce44SJohn Forte if (qd > stmf_worker_scale_down_qd)
6481fcf3ce44SJohn Forte stmf_worker_scale_down_qd = qd;
6482fcf3ce44SJohn Forte if (stmf_worker_scale_down_timer == 0) {
6483fcf3ce44SJohn Forte stmf_worker_scale_down_timer = ddi_get_lbolt() +
6484fcf3ce44SJohn Forte drv_usectohz(stmf_worker_scale_down_delay *
6485fcf3ce44SJohn Forte 1000 * 1000);
6486fcf3ce44SJohn Forte return;
6487fcf3ce44SJohn Forte }
6488fcf3ce44SJohn Forte if (ddi_get_lbolt() < stmf_worker_scale_down_timer) {
6489fcf3ce44SJohn Forte return;
6490fcf3ce44SJohn Forte }
6491fcf3ce44SJohn Forte /* Its time to reduce the workers */
6492fcf3ce44SJohn Forte if (stmf_worker_scale_down_qd < stmf_i_min_nworkers)
6493fcf3ce44SJohn Forte stmf_worker_scale_down_qd = stmf_i_min_nworkers;
6494fcf3ce44SJohn Forte if (stmf_worker_scale_down_qd > stmf_i_max_nworkers)
6495fcf3ce44SJohn Forte stmf_worker_scale_down_qd = stmf_i_max_nworkers;
6496fcf3ce44SJohn Forte if (stmf_worker_scale_down_qd == stmf_nworkers_cur)
6497fcf3ce44SJohn Forte return;
6498fcf3ce44SJohn Forte workers_needed = stmf_worker_scale_down_qd;
6499fcf3ce44SJohn Forte stmf_worker_scale_down_qd = 0;
6500fcf3ce44SJohn Forte goto worker_mgmt_trigger_change;
6501fcf3ce44SJohn Forte }
6502fcf3ce44SJohn Forte stmf_worker_scale_down_qd = 0;
6503fcf3ce44SJohn Forte stmf_worker_scale_down_timer = 0;
6504fcf3ce44SJohn Forte if (qd > stmf_i_max_nworkers)
6505fcf3ce44SJohn Forte qd = stmf_i_max_nworkers;
6506fcf3ce44SJohn Forte if (qd < stmf_i_min_nworkers)
6507fcf3ce44SJohn Forte qd = stmf_i_min_nworkers;
6508fcf3ce44SJohn Forte if (qd == stmf_nworkers_cur)
6509fcf3ce44SJohn Forte return;
6510fcf3ce44SJohn Forte workers_needed = qd;
6511fcf3ce44SJohn Forte goto worker_mgmt_trigger_change;
6512fcf3ce44SJohn Forte
6513fcf3ce44SJohn Forte /* NOTREACHED */
6514fcf3ce44SJohn Forte return;
6515fcf3ce44SJohn Forte
6516fcf3ce44SJohn Forte worker_mgmt_trigger_change:
6517fcf3ce44SJohn Forte ASSERT(workers_needed != stmf_nworkers_cur);
6518fcf3ce44SJohn Forte if (workers_needed > stmf_nworkers_cur) {
6519fcf3ce44SJohn Forte stmf_nworkers_needed = workers_needed;
6520fcf3ce44SJohn Forte for (i = stmf_nworkers_cur; i < workers_needed; i++) {
6521fcf3ce44SJohn Forte w = &stmf_workers[i];
6522fcf3ce44SJohn Forte w->worker_tid = thread_create(NULL, 0, stmf_worker_task,
6523fcf3ce44SJohn Forte (void *)&stmf_workers[i], 0, &p0, TS_RUN,
6524fcf3ce44SJohn Forte minclsyspri);
6525fcf3ce44SJohn Forte }
6526fcf3ce44SJohn Forte return;
6527fcf3ce44SJohn Forte }
6528fcf3ce44SJohn Forte /* At this point we know that we are decreasing the # of workers */
6529fcf3ce44SJohn Forte stmf_nworkers_accepting_cmds = workers_needed;
6530fcf3ce44SJohn Forte stmf_nworkers_needed = workers_needed;
6531fcf3ce44SJohn Forte /* Signal the workers that its time to quit */
6532fcf3ce44SJohn Forte for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) {
6533fcf3ce44SJohn Forte w = &stmf_workers[i];
6534fcf3ce44SJohn Forte ASSERT(w && (w->worker_flags & STMF_WORKER_STARTED));
6535fcf3ce44SJohn Forte mutex_enter(&w->worker_lock);
6536fcf3ce44SJohn Forte w->worker_flags |= STMF_WORKER_TERMINATE;
6537fcf3ce44SJohn Forte if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0)
6538fcf3ce44SJohn Forte cv_signal(&w->worker_cv);
6539fcf3ce44SJohn Forte mutex_exit(&w->worker_lock);
6540fcf3ce44SJohn Forte }
6541fcf3ce44SJohn Forte }
6542fcf3ce44SJohn Forte
6543fcf3ce44SJohn Forte /*
6544fcf3ce44SJohn Forte * Fills out a dbuf from stmf_xfer_data_t (contained in the db_lu_private).
6545fcf3ce44SJohn Forte * If all the data has been filled out, frees the xd and makes
6546fcf3ce44SJohn Forte * db_lu_private NULL.
6547fcf3ce44SJohn Forte */
6548fcf3ce44SJohn Forte void
stmf_xd_to_dbuf(stmf_data_buf_t * dbuf,int set_rel_off)654991159e90SJohn Forte stmf_xd_to_dbuf(stmf_data_buf_t *dbuf, int set_rel_off)
6550fcf3ce44SJohn Forte {
6551fcf3ce44SJohn Forte stmf_xfer_data_t *xd;
6552fcf3ce44SJohn Forte uint8_t *p;
6553fcf3ce44SJohn Forte int i;
6554fcf3ce44SJohn Forte uint32_t s;
6555fcf3ce44SJohn Forte
6556fcf3ce44SJohn Forte xd = (stmf_xfer_data_t *)dbuf->db_lu_private;
6557fcf3ce44SJohn Forte dbuf->db_data_size = 0;
655891159e90SJohn Forte if (set_rel_off)
6559fcf3ce44SJohn Forte dbuf->db_relative_offset = xd->size_done;
6560fcf3ce44SJohn Forte for (i = 0; i < dbuf->db_sglist_length; i++) {
6561fcf3ce44SJohn Forte s = min(xd->size_left, dbuf->db_sglist[i].seg_length);
6562fcf3ce44SJohn Forte p = &xd->buf[xd->size_done];
6563fcf3ce44SJohn Forte bcopy(p, dbuf->db_sglist[i].seg_addr, s);
6564fcf3ce44SJohn Forte xd->size_left -= s;
6565fcf3ce44SJohn Forte xd->size_done += s;
6566fcf3ce44SJohn Forte dbuf->db_data_size += s;
6567fcf3ce44SJohn Forte if (xd->size_left == 0) {
6568fcf3ce44SJohn Forte kmem_free(xd, xd->alloc_size);
6569fcf3ce44SJohn Forte dbuf->db_lu_private = NULL;
6570fcf3ce44SJohn Forte return;
6571fcf3ce44SJohn Forte }
6572fcf3ce44SJohn Forte }
6573fcf3ce44SJohn Forte }
6574fcf3ce44SJohn Forte
6575fcf3ce44SJohn Forte /* ARGSUSED */
6576fcf3ce44SJohn Forte stmf_status_t
stmf_dlun0_task_alloc(scsi_task_t * task)6577fcf3ce44SJohn Forte stmf_dlun0_task_alloc(scsi_task_t *task)
6578fcf3ce44SJohn Forte {
6579fcf3ce44SJohn Forte return (STMF_SUCCESS);
6580fcf3ce44SJohn Forte }
6581fcf3ce44SJohn Forte
6582fcf3ce44SJohn Forte void
stmf_dlun0_new_task(scsi_task_t * task,stmf_data_buf_t * dbuf)6583fcf3ce44SJohn Forte stmf_dlun0_new_task(scsi_task_t *task, stmf_data_buf_t *dbuf)
6584fcf3ce44SJohn Forte {
6585fcf3ce44SJohn Forte uint8_t *cdbp = (uint8_t *)&task->task_cdb[0];
6586fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss;
6587fcf3ce44SJohn Forte uint32_t sz, minsz;
6588fcf3ce44SJohn Forte uint8_t *p;
6589fcf3ce44SJohn Forte stmf_xfer_data_t *xd;
6590fcf3ce44SJohn Forte uint8_t inq_page_length = 31;
6591fcf3ce44SJohn Forte
6592fcf3ce44SJohn Forte if (task->task_mgmt_function) {
6593fcf3ce44SJohn Forte stmf_scsilib_handle_task_mgmt(task);
6594fcf3ce44SJohn Forte return;
6595fcf3ce44SJohn Forte }
6596fcf3ce44SJohn Forte
6597fcf3ce44SJohn Forte switch (cdbp[0]) {
6598fcf3ce44SJohn Forte case SCMD_INQUIRY:
6599fcf3ce44SJohn Forte /*
6600fcf3ce44SJohn Forte * Basic protocol checks. In addition, only reply to
6601fcf3ce44SJohn Forte * standard inquiry. Otherwise, the LU provider needs
6602fcf3ce44SJohn Forte * to respond.
6603fcf3ce44SJohn Forte */
6604fcf3ce44SJohn Forte
6605fcf3ce44SJohn Forte if (cdbp[2] || (cdbp[1] & 1) || cdbp[5]) {
6606fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
6607fcf3ce44SJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
6608fcf3ce44SJohn Forte return;
6609fcf3ce44SJohn Forte }
6610fcf3ce44SJohn Forte
6611fcf3ce44SJohn Forte task->task_cmd_xfer_length =
6612fcf3ce44SJohn Forte (((uint32_t)cdbp[3]) << 8) | cdbp[4];
6613fcf3ce44SJohn Forte
6614fcf3ce44SJohn Forte if (task->task_additional_flags &
6615fcf3ce44SJohn Forte TASK_AF_NO_EXPECTED_XFER_LENGTH) {
6616fcf3ce44SJohn Forte task->task_expected_xfer_length =
6617fcf3ce44SJohn Forte task->task_cmd_xfer_length;
6618fcf3ce44SJohn Forte }
6619fcf3ce44SJohn Forte
6620fcf3ce44SJohn Forte sz = min(task->task_expected_xfer_length,
6621fcf3ce44SJohn Forte min(36, task->task_cmd_xfer_length));
6622fcf3ce44SJohn Forte minsz = 36;
6623fcf3ce44SJohn Forte
6624fcf3ce44SJohn Forte if (sz == 0) {
6625fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6626fcf3ce44SJohn Forte return;
6627fcf3ce44SJohn Forte }
6628fcf3ce44SJohn Forte
6629fcf3ce44SJohn Forte if (dbuf && (dbuf->db_sglist[0].seg_length < 36)) {
6630fcf3ce44SJohn Forte /*
6631fcf3ce44SJohn Forte * Ignore any preallocated dbuf if the size is less
6632fcf3ce44SJohn Forte * than 36. It will be freed during the task_free.
6633fcf3ce44SJohn Forte */
6634fcf3ce44SJohn Forte dbuf = NULL;
6635fcf3ce44SJohn Forte }
6636fcf3ce44SJohn Forte if (dbuf == NULL)
6637fcf3ce44SJohn Forte dbuf = stmf_alloc_dbuf(task, minsz, &minsz, 0);
6638fcf3ce44SJohn Forte if ((dbuf == NULL) || (dbuf->db_sglist[0].seg_length < sz)) {
6639fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6640fcf3ce44SJohn Forte STMF_ALLOC_FAILURE, NULL);
6641fcf3ce44SJohn Forte return;
6642fcf3ce44SJohn Forte }
6643fcf3ce44SJohn Forte dbuf->db_lu_private = NULL;
6644fcf3ce44SJohn Forte
6645fcf3ce44SJohn Forte p = dbuf->db_sglist[0].seg_addr;
6646fcf3ce44SJohn Forte
6647fcf3ce44SJohn Forte /*
6648fcf3ce44SJohn Forte * Standard inquiry handling only.
6649fcf3ce44SJohn Forte */
6650fcf3ce44SJohn Forte
6651fcf3ce44SJohn Forte bzero(p, inq_page_length + 5);
6652fcf3ce44SJohn Forte
6653fcf3ce44SJohn Forte p[0] = DPQ_SUPPORTED | DTYPE_UNKNOWN;
6654fcf3ce44SJohn Forte p[2] = 5;
6655fcf3ce44SJohn Forte p[3] = 0x12;
6656fcf3ce44SJohn Forte p[4] = inq_page_length;
6657fcf3ce44SJohn Forte p[6] = 0x80;
6658fcf3ce44SJohn Forte
6659fcf3ce44SJohn Forte (void) strncpy((char *)p+8, "SUN ", 8);
6660fcf3ce44SJohn Forte (void) strncpy((char *)p+16, "COMSTAR ", 16);
6661fcf3ce44SJohn Forte (void) strncpy((char *)p+32, "1.0 ", 4);
6662fcf3ce44SJohn Forte
6663fcf3ce44SJohn Forte dbuf->db_data_size = sz;
6664fcf3ce44SJohn Forte dbuf->db_relative_offset = 0;
6665fcf3ce44SJohn Forte dbuf->db_flags = DB_DIRECTION_TO_RPORT;
6666fcf3ce44SJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
6667fcf3ce44SJohn Forte
6668fcf3ce44SJohn Forte return;
6669fcf3ce44SJohn Forte
6670fcf3ce44SJohn Forte case SCMD_REPORT_LUNS:
6671fcf3ce44SJohn Forte task->task_cmd_xfer_length =
6672fcf3ce44SJohn Forte ((((uint32_t)task->task_cdb[6]) << 24) |
6673fcf3ce44SJohn Forte (((uint32_t)task->task_cdb[7]) << 16) |
6674fcf3ce44SJohn Forte (((uint32_t)task->task_cdb[8]) << 8) |
6675fcf3ce44SJohn Forte ((uint32_t)task->task_cdb[9]));
6676fcf3ce44SJohn Forte
6677fcf3ce44SJohn Forte if (task->task_additional_flags &
6678fcf3ce44SJohn Forte TASK_AF_NO_EXPECTED_XFER_LENGTH) {
6679fcf3ce44SJohn Forte task->task_expected_xfer_length =
6680fcf3ce44SJohn Forte task->task_cmd_xfer_length;
6681fcf3ce44SJohn Forte }
6682fcf3ce44SJohn Forte
6683fcf3ce44SJohn Forte sz = min(task->task_expected_xfer_length,
6684fcf3ce44SJohn Forte task->task_cmd_xfer_length);
6685fcf3ce44SJohn Forte
6686fcf3ce44SJohn Forte if (sz < 16) {
6687fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
6688fcf3ce44SJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
6689fcf3ce44SJohn Forte return;
6690fcf3ce44SJohn Forte }
6691fcf3ce44SJohn Forte
6692fcf3ce44SJohn Forte iss = (stmf_i_scsi_session_t *)
6693fcf3ce44SJohn Forte task->task_session->ss_stmf_private;
6694fcf3ce44SJohn Forte rw_enter(iss->iss_lockp, RW_WRITER);
6695fcf3ce44SJohn Forte xd = stmf_session_prepare_report_lun_data(iss->iss_sm);
6696fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
6697fcf3ce44SJohn Forte
6698fcf3ce44SJohn Forte if (xd == NULL) {
6699fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6700fcf3ce44SJohn Forte STMF_ALLOC_FAILURE, NULL);
6701fcf3ce44SJohn Forte return;
6702fcf3ce44SJohn Forte }
6703fcf3ce44SJohn Forte
6704fcf3ce44SJohn Forte sz = min(sz, xd->size_left);
6705fcf3ce44SJohn Forte xd->size_left = sz;
6706fcf3ce44SJohn Forte minsz = min(512, sz);
6707fcf3ce44SJohn Forte
6708fcf3ce44SJohn Forte if (dbuf == NULL)
6709fcf3ce44SJohn Forte dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0);
6710fcf3ce44SJohn Forte if (dbuf == NULL) {
6711fcf3ce44SJohn Forte kmem_free(xd, xd->alloc_size);
6712fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6713fcf3ce44SJohn Forte STMF_ALLOC_FAILURE, NULL);
6714fcf3ce44SJohn Forte return;
6715fcf3ce44SJohn Forte }
6716fcf3ce44SJohn Forte dbuf->db_lu_private = xd;
671791159e90SJohn Forte stmf_xd_to_dbuf(dbuf, 1);
6718fcf3ce44SJohn Forte
6719fcf3ce44SJohn Forte atomic_and_32(&iss->iss_flags,
6720fcf3ce44SJohn Forte ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS));
6721fcf3ce44SJohn Forte dbuf->db_flags = DB_DIRECTION_TO_RPORT;
6722fcf3ce44SJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
6723fcf3ce44SJohn Forte return;
6724fcf3ce44SJohn Forte }
6725fcf3ce44SJohn Forte
6726fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE);
6727fcf3ce44SJohn Forte }
6728fcf3ce44SJohn Forte
6729fcf3ce44SJohn Forte void
stmf_dlun0_dbuf_done(scsi_task_t * task,stmf_data_buf_t * dbuf)6730fcf3ce44SJohn Forte stmf_dlun0_dbuf_done(scsi_task_t *task, stmf_data_buf_t *dbuf)
6731fcf3ce44SJohn Forte {
673245039663SJohn Forte stmf_i_scsi_task_t *itask =
673345039663SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
673445039663SJohn Forte
6735fcf3ce44SJohn Forte if (dbuf->db_xfer_status != STMF_SUCCESS) {
6736fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6737fcf3ce44SJohn Forte dbuf->db_xfer_status, NULL);
6738fcf3ce44SJohn Forte return;
6739fcf3ce44SJohn Forte }
674091159e90SJohn Forte task->task_nbytes_transferred += dbuf->db_data_size;
6741fcf3ce44SJohn Forte if (dbuf->db_lu_private) {
6742fcf3ce44SJohn Forte /* There is more */
674391159e90SJohn Forte stmf_xd_to_dbuf(dbuf, 1);
6744fcf3ce44SJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
6745fcf3ce44SJohn Forte return;
6746fcf3ce44SJohn Forte }
674791159e90SJohn Forte
674891159e90SJohn Forte stmf_free_dbuf(task, dbuf);
674945039663SJohn Forte /*
675045039663SJohn Forte * If this is a proxy task, it will need to be completed from the
675145039663SJohn Forte * proxy port provider. This message lets pppt know that the xfer
675245039663SJohn Forte * is complete. When we receive the status from pppt, we will
675345039663SJohn Forte * then relay that status back to the lport.
675445039663SJohn Forte */
675545039663SJohn Forte if (itask->itask_flags & ITASK_PROXY_TASK) {
675645039663SJohn Forte stmf_ic_msg_t *ic_xfer_done_msg = NULL;
675745039663SJohn Forte stmf_status_t ic_ret = STMF_FAILURE;
675845039663SJohn Forte uint64_t session_msg_id;
675945039663SJohn Forte mutex_enter(&stmf_state.stmf_lock);
676045039663SJohn Forte session_msg_id = stmf_proxy_msg_id++;
676145039663SJohn Forte mutex_exit(&stmf_state.stmf_lock);
676245039663SJohn Forte /* send xfer done status to pppt */
676345039663SJohn Forte ic_xfer_done_msg = ic_scsi_data_xfer_done_msg_alloc(
676445039663SJohn Forte itask->itask_proxy_msg_id,
676545039663SJohn Forte task->task_session->ss_session_id,
676645039663SJohn Forte STMF_SUCCESS, session_msg_id);
676745039663SJohn Forte if (ic_xfer_done_msg) {
676845039663SJohn Forte ic_ret = ic_tx_msg(ic_xfer_done_msg);
676945039663SJohn Forte if (ic_ret != STMF_IC_MSG_SUCCESS) {
677045039663SJohn Forte cmn_err(CE_WARN, "unable to xmit session msg");
677145039663SJohn Forte }
677245039663SJohn Forte }
677345039663SJohn Forte /* task will be completed from pppt */
677445039663SJohn Forte return;
677545039663SJohn Forte }
6776fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6777fcf3ce44SJohn Forte }
6778fcf3ce44SJohn Forte
6779fcf3ce44SJohn Forte /* ARGSUSED */
6780fcf3ce44SJohn Forte void
stmf_dlun0_status_done(scsi_task_t * task)6781fcf3ce44SJohn Forte stmf_dlun0_status_done(scsi_task_t *task)
6782fcf3ce44SJohn Forte {
6783fcf3ce44SJohn Forte }
6784fcf3ce44SJohn Forte
6785fcf3ce44SJohn Forte /* ARGSUSED */
6786fcf3ce44SJohn Forte void
stmf_dlun0_task_free(scsi_task_t * task)6787fcf3ce44SJohn Forte stmf_dlun0_task_free(scsi_task_t *task)
6788fcf3ce44SJohn Forte {
6789fcf3ce44SJohn Forte }
6790fcf3ce44SJohn Forte
6791fcf3ce44SJohn Forte /* ARGSUSED */
6792fcf3ce44SJohn Forte stmf_status_t
stmf_dlun0_abort(struct stmf_lu * lu,int abort_cmd,void * arg,uint32_t flags)6793fcf3ce44SJohn Forte stmf_dlun0_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags)
6794fcf3ce44SJohn Forte {
6795fcf3ce44SJohn Forte scsi_task_t *task = (scsi_task_t *)arg;
6796fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask =
6797fcf3ce44SJohn Forte (stmf_i_scsi_task_t *)task->task_stmf_private;
6798fcf3ce44SJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
6799fcf3ce44SJohn Forte int i;
6800fcf3ce44SJohn Forte uint8_t map;
6801fcf3ce44SJohn Forte
6802fcf3ce44SJohn Forte if ((task->task_mgmt_function) && (itask->itask_flags &
6803fcf3ce44SJohn Forte (ITASK_CAUSING_LU_RESET | ITASK_CAUSING_TARGET_RESET))) {
6804fcf3ce44SJohn Forte switch (task->task_mgmt_function) {
6805fcf3ce44SJohn Forte case TM_ABORT_TASK:
6806fcf3ce44SJohn Forte case TM_ABORT_TASK_SET:
6807fcf3ce44SJohn Forte case TM_CLEAR_TASK_SET:
6808fcf3ce44SJohn Forte case TM_LUN_RESET:
6809fcf3ce44SJohn Forte atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
6810fcf3ce44SJohn Forte break;
6811fcf3ce44SJohn Forte case TM_TARGET_RESET:
6812fcf3ce44SJohn Forte case TM_TARGET_COLD_RESET:
6813fcf3ce44SJohn Forte case TM_TARGET_WARM_RESET:
6814fcf3ce44SJohn Forte stmf_abort_target_reset(task);
6815fcf3ce44SJohn Forte break;
6816fcf3ce44SJohn Forte }
6817fcf3ce44SJohn Forte return (STMF_ABORT_SUCCESS);
6818fcf3ce44SJohn Forte }
6819fcf3ce44SJohn Forte
6820fcf3ce44SJohn Forte /*
6821fcf3ce44SJohn Forte * OK so its not a task mgmt. Make sure we free any xd sitting
6822fcf3ce44SJohn Forte * inside any dbuf.
6823fcf3ce44SJohn Forte */
6824fcf3ce44SJohn Forte if ((map = itask->itask_allocated_buf_map) != 0) {
6825fcf3ce44SJohn Forte for (i = 0; i < 4; i++) {
6826fcf3ce44SJohn Forte if ((map & 1) &&
6827fcf3ce44SJohn Forte ((itask->itask_dbufs[i])->db_lu_private)) {
6828fcf3ce44SJohn Forte stmf_xfer_data_t *xd;
6829fcf3ce44SJohn Forte stmf_data_buf_t *dbuf;
6830fcf3ce44SJohn Forte
6831fcf3ce44SJohn Forte dbuf = itask->itask_dbufs[i];
6832fcf3ce44SJohn Forte xd = (stmf_xfer_data_t *)dbuf->db_lu_private;
6833fcf3ce44SJohn Forte dbuf->db_lu_private = NULL;
6834fcf3ce44SJohn Forte kmem_free(xd, xd->alloc_size);
6835fcf3ce44SJohn Forte }
6836fcf3ce44SJohn Forte map >>= 1;
6837fcf3ce44SJohn Forte }
6838fcf3ce44SJohn Forte }
6839fcf3ce44SJohn Forte return (STMF_ABORT_SUCCESS);
6840fcf3ce44SJohn Forte }
6841fcf3ce44SJohn Forte
6842fcf3ce44SJohn Forte void
stmf_dlun0_task_poll(struct scsi_task * task)6843fcf3ce44SJohn Forte stmf_dlun0_task_poll(struct scsi_task *task)
6844fcf3ce44SJohn Forte {
6845fcf3ce44SJohn Forte /* Right now we only do this for handling task management functions */
6846fcf3ce44SJohn Forte ASSERT(task->task_mgmt_function);
6847fcf3ce44SJohn Forte
6848fcf3ce44SJohn Forte switch (task->task_mgmt_function) {
6849fcf3ce44SJohn Forte case TM_ABORT_TASK:
6850fcf3ce44SJohn Forte case TM_ABORT_TASK_SET:
6851fcf3ce44SJohn Forte case TM_CLEAR_TASK_SET:
6852fcf3ce44SJohn Forte case TM_LUN_RESET:
6853fcf3ce44SJohn Forte (void) stmf_lun_reset_poll(task->task_lu, task, 0);
6854fcf3ce44SJohn Forte return;
6855fcf3ce44SJohn Forte case TM_TARGET_RESET:
6856fcf3ce44SJohn Forte case TM_TARGET_COLD_RESET:
6857fcf3ce44SJohn Forte case TM_TARGET_WARM_RESET:
6858fcf3ce44SJohn Forte stmf_target_reset_poll(task);
6859fcf3ce44SJohn Forte return;
6860fcf3ce44SJohn Forte }
6861fcf3ce44SJohn Forte }
6862fcf3ce44SJohn Forte
6863fcf3ce44SJohn Forte /* ARGSUSED */
6864fcf3ce44SJohn Forte void
stmf_dlun0_ctl(struct stmf_lu * lu,int cmd,void * arg)6865fcf3ce44SJohn Forte stmf_dlun0_ctl(struct stmf_lu *lu, int cmd, void *arg)
6866fcf3ce44SJohn Forte {
6867fcf3ce44SJohn Forte /* This function will never be called */
6868fcf3ce44SJohn Forte cmn_err(CE_WARN, "stmf_dlun0_ctl called with cmd %x", cmd);
6869fcf3ce44SJohn Forte }
6870fcf3ce44SJohn Forte
6871fcf3ce44SJohn Forte void
stmf_dlun_init()6872fcf3ce44SJohn Forte stmf_dlun_init()
6873fcf3ce44SJohn Forte {
6874fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
6875fcf3ce44SJohn Forte
6876fcf3ce44SJohn Forte dlun0 = stmf_alloc(STMF_STRUCT_STMF_LU, 0, 0);
6877fcf3ce44SJohn Forte dlun0->lu_task_alloc = stmf_dlun0_task_alloc;
6878fcf3ce44SJohn Forte dlun0->lu_new_task = stmf_dlun0_new_task;
6879fcf3ce44SJohn Forte dlun0->lu_dbuf_xfer_done = stmf_dlun0_dbuf_done;
6880fcf3ce44SJohn Forte dlun0->lu_send_status_done = stmf_dlun0_status_done;
6881fcf3ce44SJohn Forte dlun0->lu_task_free = stmf_dlun0_task_free;
6882fcf3ce44SJohn Forte dlun0->lu_abort = stmf_dlun0_abort;
6883fcf3ce44SJohn Forte dlun0->lu_task_poll = stmf_dlun0_task_poll;
6884fcf3ce44SJohn Forte dlun0->lu_ctl = stmf_dlun0_ctl;
6885fcf3ce44SJohn Forte
6886fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private;
6887fcf3ce44SJohn Forte ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
6888fcf3ce44SJohn Forte }
6889fcf3ce44SJohn Forte
6890fcf3ce44SJohn Forte stmf_status_t
stmf_dlun_fini()6891fcf3ce44SJohn Forte stmf_dlun_fini()
6892fcf3ce44SJohn Forte {
6893fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
6894fcf3ce44SJohn Forte
6895fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private;
6896fcf3ce44SJohn Forte
6897fcf3ce44SJohn Forte ASSERT(ilu->ilu_ntasks == ilu->ilu_ntasks_free);
6898fcf3ce44SJohn Forte if (ilu->ilu_ntasks) {
6899fcf3ce44SJohn Forte stmf_i_scsi_task_t *itask, *nitask;
6900fcf3ce44SJohn Forte
6901fcf3ce44SJohn Forte nitask = ilu->ilu_tasks;
6902fcf3ce44SJohn Forte do {
6903fcf3ce44SJohn Forte itask = nitask;
6904fcf3ce44SJohn Forte nitask = itask->itask_lu_next;
6905fcf3ce44SJohn Forte dlun0->lu_task_free(itask->itask_task);
6906fcf3ce44SJohn Forte stmf_free(itask->itask_task);
6907fcf3ce44SJohn Forte } while (nitask != NULL);
6908fcf3ce44SJohn Forte
6909fcf3ce44SJohn Forte }
6910fcf3ce44SJohn Forte stmf_free(dlun0);
6911fcf3ce44SJohn Forte return (STMF_SUCCESS);
6912fcf3ce44SJohn Forte }
6913fcf3ce44SJohn Forte
6914fcf3ce44SJohn Forte void
stmf_abort_target_reset(scsi_task_t * task)6915fcf3ce44SJohn Forte stmf_abort_target_reset(scsi_task_t *task)
6916fcf3ce44SJohn Forte {
6917fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
6918fcf3ce44SJohn Forte task->task_session->ss_stmf_private;
6919fcf3ce44SJohn Forte stmf_lun_map_t *lm;
6920fcf3ce44SJohn Forte stmf_lun_map_ent_t *lm_ent;
6921fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
6922fcf3ce44SJohn Forte int i;
6923fcf3ce44SJohn Forte
6924fcf3ce44SJohn Forte rw_enter(iss->iss_lockp, RW_READER);
6925fcf3ce44SJohn Forte lm = iss->iss_sm;
6926fcf3ce44SJohn Forte for (i = 0; i < lm->lm_nentries; i++) {
6927fcf3ce44SJohn Forte if (lm->lm_plus[i] == NULL)
6928fcf3ce44SJohn Forte continue;
6929fcf3ce44SJohn Forte lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
6930fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private;
6931fcf3ce44SJohn Forte if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
6932fcf3ce44SJohn Forte atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
6933fcf3ce44SJohn Forte }
6934fcf3ce44SJohn Forte }
6935fcf3ce44SJohn Forte atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
6936fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
6937fcf3ce44SJohn Forte }
6938fcf3ce44SJohn Forte
6939fcf3ce44SJohn Forte /*
6940fcf3ce44SJohn Forte * The return value is only used by function managing target reset.
6941fcf3ce44SJohn Forte */
6942fcf3ce44SJohn Forte stmf_status_t
stmf_lun_reset_poll(stmf_lu_t * lu,struct scsi_task * task,int target_reset)6943fcf3ce44SJohn Forte stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task, int target_reset)
6944fcf3ce44SJohn Forte {
6945fcf3ce44SJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
6946fcf3ce44SJohn Forte int ntasks_pending;
6947fcf3ce44SJohn Forte
6948fcf3ce44SJohn Forte ntasks_pending = ilu->ilu_ntasks - ilu->ilu_ntasks_free;
6949fcf3ce44SJohn Forte /*
6950fcf3ce44SJohn Forte * This function is also used during Target reset. The idea is that
6951fcf3ce44SJohn Forte * once all the commands are aborted, call the LU's reset entry
6952fcf3ce44SJohn Forte * point (abort entry point with a reset flag). But if this Task
6953fcf3ce44SJohn Forte * mgmt is running on this LU then all the tasks cannot be aborted.
6954fcf3ce44SJohn Forte * one task (this task) will still be running which is OK.
6955fcf3ce44SJohn Forte */
6956fcf3ce44SJohn Forte if ((ntasks_pending == 0) || ((task->task_lu == lu) &&
6957fcf3ce44SJohn Forte (ntasks_pending == 1))) {
6958fcf3ce44SJohn Forte stmf_status_t ret;
6959fcf3ce44SJohn Forte
6960fcf3ce44SJohn Forte if ((task->task_mgmt_function == TM_LUN_RESET) ||
6961fcf3ce44SJohn Forte (task->task_mgmt_function == TM_TARGET_RESET) ||
6962fcf3ce44SJohn Forte (task->task_mgmt_function == TM_TARGET_WARM_RESET) ||
6963fcf3ce44SJohn Forte (task->task_mgmt_function == TM_TARGET_COLD_RESET)) {
6964fcf3ce44SJohn Forte ret = lu->lu_abort(lu, STMF_LU_RESET_STATE, task, 0);
6965fcf3ce44SJohn Forte } else {
6966fcf3ce44SJohn Forte ret = STMF_SUCCESS;
6967fcf3ce44SJohn Forte }
6968fcf3ce44SJohn Forte if (ret == STMF_SUCCESS) {
6969fcf3ce44SJohn Forte atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
6970fcf3ce44SJohn Forte }
6971fcf3ce44SJohn Forte if (target_reset) {
6972fcf3ce44SJohn Forte return (ret);
6973fcf3ce44SJohn Forte }
6974fcf3ce44SJohn Forte if (ret == STMF_SUCCESS) {
6975fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6976fcf3ce44SJohn Forte return (ret);
6977fcf3ce44SJohn Forte }
6978fcf3ce44SJohn Forte if (ret != STMF_BUSY) {
6979fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task, ret, NULL);
6980fcf3ce44SJohn Forte return (ret);
6981fcf3ce44SJohn Forte }
6982fcf3ce44SJohn Forte }
6983fcf3ce44SJohn Forte
6984fcf3ce44SJohn Forte if (target_reset) {
6985fcf3ce44SJohn Forte /* Tell target reset polling code that we are not done */
6986fcf3ce44SJohn Forte return (STMF_BUSY);
6987fcf3ce44SJohn Forte }
6988fcf3ce44SJohn Forte
6989fcf3ce44SJohn Forte if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
6990fcf3ce44SJohn Forte != STMF_SUCCESS) {
6991fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6992fcf3ce44SJohn Forte STMF_ALLOC_FAILURE, NULL);
6993fcf3ce44SJohn Forte return (STMF_SUCCESS);
6994fcf3ce44SJohn Forte }
6995fcf3ce44SJohn Forte
6996fcf3ce44SJohn Forte return (STMF_SUCCESS);
6997fcf3ce44SJohn Forte }
6998fcf3ce44SJohn Forte
6999fcf3ce44SJohn Forte void
stmf_target_reset_poll(struct scsi_task * task)7000fcf3ce44SJohn Forte stmf_target_reset_poll(struct scsi_task *task)
7001fcf3ce44SJohn Forte {
7002fcf3ce44SJohn Forte stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
7003fcf3ce44SJohn Forte task->task_session->ss_stmf_private;
7004fcf3ce44SJohn Forte stmf_lun_map_t *lm;
7005fcf3ce44SJohn Forte stmf_lun_map_ent_t *lm_ent;
7006fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
7007fcf3ce44SJohn Forte stmf_status_t ret;
7008fcf3ce44SJohn Forte int i;
7009fcf3ce44SJohn Forte int not_done = 0;
7010fcf3ce44SJohn Forte
7011fcf3ce44SJohn Forte ASSERT(iss->iss_flags & ISS_RESET_ACTIVE);
7012fcf3ce44SJohn Forte
7013fcf3ce44SJohn Forte rw_enter(iss->iss_lockp, RW_READER);
7014fcf3ce44SJohn Forte lm = iss->iss_sm;
7015fcf3ce44SJohn Forte for (i = 0; i < lm->lm_nentries; i++) {
7016fcf3ce44SJohn Forte if (lm->lm_plus[i] == NULL)
7017fcf3ce44SJohn Forte continue;
7018fcf3ce44SJohn Forte lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
7019fcf3ce44SJohn Forte ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private;
7020fcf3ce44SJohn Forte if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
7021fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
7022fcf3ce44SJohn Forte ret = stmf_lun_reset_poll(lm_ent->ent_lu, task, 1);
7023fcf3ce44SJohn Forte rw_enter(iss->iss_lockp, RW_READER);
7024fcf3ce44SJohn Forte if (ret == STMF_SUCCESS)
7025fcf3ce44SJohn Forte continue;
7026fcf3ce44SJohn Forte not_done = 1;
7027fcf3ce44SJohn Forte if (ret != STMF_BUSY) {
7028fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
7029fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7030fcf3ce44SJohn Forte STMF_ABORTED, NULL);
7031fcf3ce44SJohn Forte return;
7032fcf3ce44SJohn Forte }
7033fcf3ce44SJohn Forte }
7034fcf3ce44SJohn Forte }
7035fcf3ce44SJohn Forte rw_exit(iss->iss_lockp);
7036fcf3ce44SJohn Forte
7037fcf3ce44SJohn Forte if (not_done) {
7038fcf3ce44SJohn Forte if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
7039fcf3ce44SJohn Forte != STMF_SUCCESS) {
7040fcf3ce44SJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
7041fcf3ce44SJohn Forte STMF_ALLOC_FAILURE, NULL);
7042fcf3ce44SJohn Forte return;
7043fcf3ce44SJohn Forte }
7044fcf3ce44SJohn Forte return;
7045fcf3ce44SJohn Forte }
7046fcf3ce44SJohn Forte
7047fcf3ce44SJohn Forte atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
7048fcf3ce44SJohn Forte
7049fcf3ce44SJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
7050fcf3ce44SJohn Forte }
7051fcf3ce44SJohn Forte
7052fcf3ce44SJohn Forte stmf_status_t
stmf_lu_add_event(stmf_lu_t * lu,int eventid)7053fcf3ce44SJohn Forte stmf_lu_add_event(stmf_lu_t *lu, int eventid)
7054fcf3ce44SJohn Forte {
7055fcf3ce44SJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7056fcf3ce44SJohn Forte
7057fcf3ce44SJohn Forte if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7058fcf3ce44SJohn Forte return (STMF_INVALID_ARG);
7059fcf3ce44SJohn Forte }
7060fcf3ce44SJohn Forte
7061fcf3ce44SJohn Forte STMF_EVENT_ADD(ilu->ilu_event_hdl, eventid);
7062fcf3ce44SJohn Forte return (STMF_SUCCESS);
7063fcf3ce44SJohn Forte }
7064fcf3ce44SJohn Forte
7065fcf3ce44SJohn Forte stmf_status_t
stmf_lu_remove_event(stmf_lu_t * lu,int eventid)7066fcf3ce44SJohn Forte stmf_lu_remove_event(stmf_lu_t *lu, int eventid)
7067fcf3ce44SJohn Forte {
7068fcf3ce44SJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7069fcf3ce44SJohn Forte
7070fcf3ce44SJohn Forte if (eventid == STMF_EVENT_ALL) {
7071fcf3ce44SJohn Forte STMF_EVENT_CLEAR_ALL(ilu->ilu_event_hdl);
7072fcf3ce44SJohn Forte return (STMF_SUCCESS);
7073fcf3ce44SJohn Forte }
7074fcf3ce44SJohn Forte
7075fcf3ce44SJohn Forte if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7076fcf3ce44SJohn Forte return (STMF_INVALID_ARG);
7077fcf3ce44SJohn Forte }
7078fcf3ce44SJohn Forte
7079fcf3ce44SJohn Forte STMF_EVENT_REMOVE(ilu->ilu_event_hdl, eventid);
7080fcf3ce44SJohn Forte return (STMF_SUCCESS);
7081fcf3ce44SJohn Forte }
7082fcf3ce44SJohn Forte
7083fcf3ce44SJohn Forte stmf_status_t
stmf_lport_add_event(stmf_local_port_t * lport,int eventid)7084fcf3ce44SJohn Forte stmf_lport_add_event(stmf_local_port_t *lport, int eventid)
7085fcf3ce44SJohn Forte {
7086fcf3ce44SJohn Forte stmf_i_local_port_t *ilport =
7087fcf3ce44SJohn Forte (stmf_i_local_port_t *)lport->lport_stmf_private;
7088fcf3ce44SJohn Forte
7089fcf3ce44SJohn Forte if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7090fcf3ce44SJohn Forte return (STMF_INVALID_ARG);
7091fcf3ce44SJohn Forte }
7092fcf3ce44SJohn Forte
7093fcf3ce44SJohn Forte STMF_EVENT_ADD(ilport->ilport_event_hdl, eventid);
7094fcf3ce44SJohn Forte return (STMF_SUCCESS);
7095fcf3ce44SJohn Forte }
7096fcf3ce44SJohn Forte
7097fcf3ce44SJohn Forte stmf_status_t
stmf_lport_remove_event(stmf_local_port_t * lport,int eventid)7098fcf3ce44SJohn Forte stmf_lport_remove_event(stmf_local_port_t *lport, int eventid)
7099fcf3ce44SJohn Forte {
7100fcf3ce44SJohn Forte stmf_i_local_port_t *ilport =
7101fcf3ce44SJohn Forte (stmf_i_local_port_t *)lport->lport_stmf_private;
7102fcf3ce44SJohn Forte
7103fcf3ce44SJohn Forte if (eventid == STMF_EVENT_ALL) {
7104fcf3ce44SJohn Forte STMF_EVENT_CLEAR_ALL(ilport->ilport_event_hdl);
7105fcf3ce44SJohn Forte return (STMF_SUCCESS);
7106fcf3ce44SJohn Forte }
7107fcf3ce44SJohn Forte
7108fcf3ce44SJohn Forte if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
7109fcf3ce44SJohn Forte return (STMF_INVALID_ARG);
7110fcf3ce44SJohn Forte }
7111fcf3ce44SJohn Forte
7112fcf3ce44SJohn Forte STMF_EVENT_REMOVE(ilport->ilport_event_hdl, eventid);
7113fcf3ce44SJohn Forte return (STMF_SUCCESS);
7114fcf3ce44SJohn Forte }
7115fcf3ce44SJohn Forte
7116fcf3ce44SJohn Forte void
stmf_generate_lu_event(stmf_i_lu_t * ilu,int eventid,void * arg,uint32_t flags)7117fcf3ce44SJohn Forte stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid, void *arg, uint32_t flags)
7118fcf3ce44SJohn Forte {
7119fcf3ce44SJohn Forte if (STMF_EVENT_ENABLED(ilu->ilu_event_hdl, eventid) &&
7120fcf3ce44SJohn Forte (ilu->ilu_lu->lu_event_handler != NULL)) {
7121fcf3ce44SJohn Forte ilu->ilu_lu->lu_event_handler(ilu->ilu_lu, eventid, arg, flags);
7122fcf3ce44SJohn Forte }
7123fcf3ce44SJohn Forte }
7124fcf3ce44SJohn Forte
7125fcf3ce44SJohn Forte void
stmf_generate_lport_event(stmf_i_local_port_t * ilport,int eventid,void * arg,uint32_t flags)7126fcf3ce44SJohn Forte stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid, void *arg,
7127fcf3ce44SJohn Forte uint32_t flags)
7128fcf3ce44SJohn Forte {
7129fcf3ce44SJohn Forte if (STMF_EVENT_ENABLED(ilport->ilport_event_hdl, eventid) &&
7130fcf3ce44SJohn Forte (ilport->ilport_lport->lport_event_handler != NULL)) {
7131fcf3ce44SJohn Forte ilport->ilport_lport->lport_event_handler(
7132fcf3ce44SJohn Forte ilport->ilport_lport, eventid, arg, flags);
7133fcf3ce44SJohn Forte }
7134fcf3ce44SJohn Forte }
7135fcf3ce44SJohn Forte
7136427fcaf8Stim szeto /*
7137427fcaf8Stim szeto * With the possibility of having multiple itl sessions pointing to the
7138427fcaf8Stim szeto * same itl_kstat_info, the ilu_kstat_lock mutex is used to synchronize
7139427fcaf8Stim szeto * the kstat update of the ilu_kstat_io, itl_kstat_taskq and itl_kstat_lu_xfer
7140427fcaf8Stim szeto * statistics.
7141427fcaf8Stim szeto */
7142427fcaf8Stim szeto void
stmf_itl_task_start(stmf_i_scsi_task_t * itask)7143427fcaf8Stim szeto stmf_itl_task_start(stmf_i_scsi_task_t *itask)
7144427fcaf8Stim szeto {
7145427fcaf8Stim szeto stmf_itl_data_t *itl = itask->itask_itl_datap;
7146427fcaf8Stim szeto scsi_task_t *task = itask->itask_task;
7147427fcaf8Stim szeto stmf_i_lu_t *ilu;
7148427fcaf8Stim szeto
7149427fcaf8Stim szeto if (itl == NULL || task->task_lu == dlun0)
7150427fcaf8Stim szeto return;
7151427fcaf8Stim szeto ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7152427fcaf8Stim szeto itask->itask_start_timestamp = gethrtime();
715309409df0SJeff Biseda if (ilu->ilu_kstat_io != NULL) {
715409409df0SJeff Biseda mutex_enter(ilu->ilu_kstat_io->ks_lock);
7155427fcaf8Stim szeto stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_enter);
7156427fcaf8Stim szeto mutex_exit(ilu->ilu_kstat_io->ks_lock);
715709409df0SJeff Biseda }
7158427fcaf8Stim szeto
7159427fcaf8Stim szeto stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_enter);
7160427fcaf8Stim szeto }
7161427fcaf8Stim szeto
7162427fcaf8Stim szeto void
stmf_itl_lu_new_task(stmf_i_scsi_task_t * itask)7163427fcaf8Stim szeto stmf_itl_lu_new_task(stmf_i_scsi_task_t *itask)
7164427fcaf8Stim szeto {
7165427fcaf8Stim szeto stmf_itl_data_t *itl = itask->itask_itl_datap;
7166427fcaf8Stim szeto scsi_task_t *task = itask->itask_task;
7167427fcaf8Stim szeto stmf_i_lu_t *ilu;
7168427fcaf8Stim szeto
7169427fcaf8Stim szeto if (itl == NULL || task->task_lu == dlun0)
7170427fcaf8Stim szeto return;
7171427fcaf8Stim szeto ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
717209409df0SJeff Biseda if (ilu->ilu_kstat_io != NULL) {
7173427fcaf8Stim szeto mutex_enter(ilu->ilu_kstat_io->ks_lock);
7174427fcaf8Stim szeto stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_to_runq);
7175427fcaf8Stim szeto mutex_exit(ilu->ilu_kstat_io->ks_lock);
717609409df0SJeff Biseda }
7177427fcaf8Stim szeto
7178427fcaf8Stim szeto stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_to_runq);
7179427fcaf8Stim szeto }
7180427fcaf8Stim szeto
7181427fcaf8Stim szeto void
stmf_itl_task_done(stmf_i_scsi_task_t * itask)7182427fcaf8Stim szeto stmf_itl_task_done(stmf_i_scsi_task_t *itask)
7183427fcaf8Stim szeto {
7184427fcaf8Stim szeto stmf_itl_data_t *itl = itask->itask_itl_datap;
7185427fcaf8Stim szeto scsi_task_t *task = itask->itask_task;
7186427fcaf8Stim szeto stmf_i_lu_t *ilu;
7187427fcaf8Stim szeto
718809409df0SJeff Biseda itask->itask_done_timestamp = gethrtime();
718909409df0SJeff Biseda
7190427fcaf8Stim szeto if (itl == NULL || task->task_lu == dlun0)
7191427fcaf8Stim szeto return;
7192427fcaf8Stim szeto ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7193427fcaf8Stim szeto
719409409df0SJeff Biseda if (ilu->ilu_kstat_io == NULL)
719509409df0SJeff Biseda return;
719609409df0SJeff Biseda
7197427fcaf8Stim szeto mutex_enter(ilu->ilu_kstat_io->ks_lock);
7198427fcaf8Stim szeto
7199427fcaf8Stim szeto if (itask->itask_flags & ITASK_KSTAT_IN_RUNQ) {
7200427fcaf8Stim szeto stmf_update_kstat_lu_q(task, kstat_runq_exit);
7201427fcaf8Stim szeto mutex_exit(ilu->ilu_kstat_io->ks_lock);
7202427fcaf8Stim szeto stmf_update_kstat_lport_q(task, kstat_runq_exit);
7203427fcaf8Stim szeto } else {
7204427fcaf8Stim szeto stmf_update_kstat_lu_q(task, kstat_waitq_exit);
7205427fcaf8Stim szeto mutex_exit(ilu->ilu_kstat_io->ks_lock);
7206427fcaf8Stim szeto stmf_update_kstat_lport_q(task, kstat_waitq_exit);
7207427fcaf8Stim szeto }
7208427fcaf8Stim szeto }
7209427fcaf8Stim szeto
7210427fcaf8Stim szeto static void
stmf_lport_xfer_start(stmf_i_scsi_task_t * itask,stmf_data_buf_t * dbuf)7211427fcaf8Stim szeto stmf_lport_xfer_start(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7212427fcaf8Stim szeto {
7213427fcaf8Stim szeto stmf_itl_data_t *itl = itask->itask_itl_datap;
7214427fcaf8Stim szeto
7215427fcaf8Stim szeto if (itl == NULL)
7216427fcaf8Stim szeto return;
7217427fcaf8Stim szeto
7218427fcaf8Stim szeto DTRACE_PROBE2(scsi__xfer__start, scsi_task_t *, itask->itask_task,
7219427fcaf8Stim szeto stmf_data_buf_t *, dbuf);
7220427fcaf8Stim szeto
7221427fcaf8Stim szeto dbuf->db_xfer_start_timestamp = gethrtime();
7222427fcaf8Stim szeto }
7223427fcaf8Stim szeto
7224427fcaf8Stim szeto static void
stmf_lport_xfer_done(stmf_i_scsi_task_t * itask,stmf_data_buf_t * dbuf)7225427fcaf8Stim szeto stmf_lport_xfer_done(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7226427fcaf8Stim szeto {
7227427fcaf8Stim szeto stmf_itl_data_t *itl = itask->itask_itl_datap;
7228427fcaf8Stim szeto hrtime_t elapsed_time;
7229427fcaf8Stim szeto uint64_t xfer_size;
7230427fcaf8Stim szeto
7231427fcaf8Stim szeto if (itl == NULL)
7232427fcaf8Stim szeto return;
7233427fcaf8Stim szeto
7234427fcaf8Stim szeto xfer_size = (dbuf->db_xfer_status == STMF_SUCCESS) ?
7235427fcaf8Stim szeto dbuf->db_data_size : 0;
7236427fcaf8Stim szeto
7237427fcaf8Stim szeto elapsed_time = gethrtime() - dbuf->db_xfer_start_timestamp;
7238427fcaf8Stim szeto if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
7239427fcaf8Stim szeto atomic_add_64((uint64_t *)&itask->itask_lport_read_time,
7240427fcaf8Stim szeto elapsed_time);
7241427fcaf8Stim szeto atomic_add_64((uint64_t *)&itask->itask_read_xfer,
7242427fcaf8Stim szeto xfer_size);
7243427fcaf8Stim szeto } else {
7244427fcaf8Stim szeto atomic_add_64((uint64_t *)&itask->itask_lport_write_time,
7245427fcaf8Stim szeto elapsed_time);
7246427fcaf8Stim szeto atomic_add_64((uint64_t *)&itask->itask_write_xfer,
7247427fcaf8Stim szeto xfer_size);
7248427fcaf8Stim szeto }
7249427fcaf8Stim szeto
7250427fcaf8Stim szeto DTRACE_PROBE3(scsi__xfer__end, scsi_task_t *, itask->itask_task,
7251427fcaf8Stim szeto stmf_data_buf_t *, dbuf, hrtime_t, elapsed_time);
7252427fcaf8Stim szeto
7253427fcaf8Stim szeto dbuf->db_xfer_start_timestamp = 0;
7254427fcaf8Stim szeto }
7255427fcaf8Stim szeto
7256fcf3ce44SJohn Forte void
stmf_svc_init()7257fcf3ce44SJohn Forte stmf_svc_init()
7258fcf3ce44SJohn Forte {
7259fcf3ce44SJohn Forte if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
7260fcf3ce44SJohn Forte return;
72616ac72a9cSAlexander Stetsenko stmf_state.stmf_svc_tailp = &stmf_state.stmf_svc_active;
7262fcf3ce44SJohn Forte stmf_state.stmf_svc_taskq = ddi_taskq_create(0, "STMF_SVC_TASKQ", 1,
7263fcf3ce44SJohn Forte TASKQ_DEFAULTPRI, 0);
7264fcf3ce44SJohn Forte (void) ddi_taskq_dispatch(stmf_state.stmf_svc_taskq,
7265fcf3ce44SJohn Forte stmf_svc, 0, DDI_SLEEP);
7266fcf3ce44SJohn Forte }
7267fcf3ce44SJohn Forte
7268fcf3ce44SJohn Forte stmf_status_t
stmf_svc_fini()7269fcf3ce44SJohn Forte stmf_svc_fini()
7270fcf3ce44SJohn Forte {
7271fcf3ce44SJohn Forte uint32_t i;
7272fcf3ce44SJohn Forte
7273fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
7274fcf3ce44SJohn Forte if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) {
7275fcf3ce44SJohn Forte stmf_state.stmf_svc_flags |= STMF_SVC_TERMINATE;
7276fcf3ce44SJohn Forte cv_signal(&stmf_state.stmf_cv);
7277fcf3ce44SJohn Forte }
7278fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
7279fcf3ce44SJohn Forte
7280fcf3ce44SJohn Forte /* Wait for 5 seconds */
7281fcf3ce44SJohn Forte for (i = 0; i < 500; i++) {
7282fcf3ce44SJohn Forte if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
7283fcf3ce44SJohn Forte delay(drv_usectohz(10000));
7284fcf3ce44SJohn Forte else
7285fcf3ce44SJohn Forte break;
7286fcf3ce44SJohn Forte }
7287fcf3ce44SJohn Forte if (i == 500)
7288fcf3ce44SJohn Forte return (STMF_BUSY);
7289fcf3ce44SJohn Forte
7290fcf3ce44SJohn Forte ddi_taskq_destroy(stmf_state.stmf_svc_taskq);
7291fcf3ce44SJohn Forte
7292fcf3ce44SJohn Forte return (STMF_SUCCESS);
7293fcf3ce44SJohn Forte }
7294fcf3ce44SJohn Forte
7295042f029eSAlexander Stetsenko struct stmf_svc_clocks {
7296042f029eSAlexander Stetsenko clock_t drain_start, drain_next;
7297042f029eSAlexander Stetsenko clock_t timing_start, timing_next;
7298042f029eSAlexander Stetsenko clock_t worker_delay;
7299042f029eSAlexander Stetsenko };
7300042f029eSAlexander Stetsenko
7301fcf3ce44SJohn Forte /* ARGSUSED */
7302fcf3ce44SJohn Forte void
stmf_svc(void * arg)7303fcf3ce44SJohn Forte stmf_svc(void *arg)
7304fcf3ce44SJohn Forte {
73056ac72a9cSAlexander Stetsenko stmf_svc_req_t *req;
7306fcf3ce44SJohn Forte stmf_lu_t *lu;
7307fcf3ce44SJohn Forte stmf_i_lu_t *ilu;
7308fcf3ce44SJohn Forte stmf_local_port_t *lport;
7309042f029eSAlexander Stetsenko struct stmf_svc_clocks clks = { 0 };
7310fcf3ce44SJohn Forte
7311fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
7312fcf3ce44SJohn Forte stmf_state.stmf_svc_flags |= STMF_SVC_STARTED | STMF_SVC_ACTIVE;
7313fcf3ce44SJohn Forte
73146ac72a9cSAlexander Stetsenko while (!(stmf_state.stmf_svc_flags & STMF_SVC_TERMINATE)) {
73156ac72a9cSAlexander Stetsenko if (stmf_state.stmf_svc_active == NULL) {
7316042f029eSAlexander Stetsenko stmf_svc_timeout(&clks);
73176ac72a9cSAlexander Stetsenko continue;
7318fcf3ce44SJohn Forte }
7319fcf3ce44SJohn Forte
73206ac72a9cSAlexander Stetsenko /*
73216ac72a9cSAlexander Stetsenko * Pop the front request from the active list. After this,
73226ac72a9cSAlexander Stetsenko * the request will no longer be referenced by global state,
73236ac72a9cSAlexander Stetsenko * so it should be safe to access it without holding the
73246ac72a9cSAlexander Stetsenko * stmf state lock.
73256ac72a9cSAlexander Stetsenko */
7326fcf3ce44SJohn Forte req = stmf_state.stmf_svc_active;
7327fcf3ce44SJohn Forte stmf_state.stmf_svc_active = req->svc_next;
7328fcf3ce44SJohn Forte
73296ac72a9cSAlexander Stetsenko if (stmf_state.stmf_svc_active == NULL)
73306ac72a9cSAlexander Stetsenko stmf_state.stmf_svc_tailp = &stmf_state.stmf_svc_active;
73316ac72a9cSAlexander Stetsenko
7332fcf3ce44SJohn Forte switch (req->svc_cmd) {
7333fcf3ce44SJohn Forte case STMF_CMD_LPORT_ONLINE:
7334fcf3ce44SJohn Forte /* Fallthrough */
7335fcf3ce44SJohn Forte case STMF_CMD_LPORT_OFFLINE:
73366ac72a9cSAlexander Stetsenko mutex_exit(&stmf_state.stmf_lock);
73376ac72a9cSAlexander Stetsenko lport = (stmf_local_port_t *)req->svc_obj;
73386ac72a9cSAlexander Stetsenko lport->lport_ctl(lport, req->svc_cmd, &req->svc_info);
7339fcf3ce44SJohn Forte break;
73406ac72a9cSAlexander Stetsenko case STMF_CMD_LU_ONLINE:
73416ac72a9cSAlexander Stetsenko mutex_exit(&stmf_state.stmf_lock);
73426ac72a9cSAlexander Stetsenko lu = (stmf_lu_t *)req->svc_obj;
73436ac72a9cSAlexander Stetsenko lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
73446ac72a9cSAlexander Stetsenko break;
7345fcf3ce44SJohn Forte case STMF_CMD_LU_OFFLINE:
7346fcf3ce44SJohn Forte /* Remove all mappings of this LU */
7347fcf3ce44SJohn Forte stmf_session_lu_unmapall((stmf_lu_t *)req->svc_obj);
7348fcf3ce44SJohn Forte /* Kill all the pending I/Os for this LU */
7349fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
7350fcf3ce44SJohn Forte stmf_task_lu_killall((stmf_lu_t *)req->svc_obj, NULL,
7351fcf3ce44SJohn Forte STMF_ABORTED);
73526ac72a9cSAlexander Stetsenko lu = (stmf_lu_t *)req->svc_obj;
73536ac72a9cSAlexander Stetsenko ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7354a49dc893SSaso Kiselkov stmf_wait_ilu_tasks_finish(ilu);
73556ac72a9cSAlexander Stetsenko lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
7356fcf3ce44SJohn Forte break;
7357fcf3ce44SJohn Forte default:
7358fcf3ce44SJohn Forte cmn_err(CE_PANIC, "stmf_svc: unknown cmd %d",
7359fcf3ce44SJohn Forte req->svc_cmd);
7360fcf3ce44SJohn Forte }
7361fcf3ce44SJohn Forte
736209409df0SJeff Biseda kmem_free(req, req->svc_req_alloc_size);
7363fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
73646ac72a9cSAlexander Stetsenko }
73656ac72a9cSAlexander Stetsenko
73666ac72a9cSAlexander Stetsenko stmf_state.stmf_svc_flags &= ~(STMF_SVC_STARTED | STMF_SVC_ACTIVE);
73676ac72a9cSAlexander Stetsenko mutex_exit(&stmf_state.stmf_lock);
73686ac72a9cSAlexander Stetsenko }
73696ac72a9cSAlexander Stetsenko
73706ac72a9cSAlexander Stetsenko static void
stmf_svc_timeout(struct stmf_svc_clocks * clks)7371042f029eSAlexander Stetsenko stmf_svc_timeout(struct stmf_svc_clocks *clks)
73726ac72a9cSAlexander Stetsenko {
73736ac72a9cSAlexander Stetsenko clock_t td;
73746ac72a9cSAlexander Stetsenko stmf_i_local_port_t *ilport, *next_ilport;
73756ac72a9cSAlexander Stetsenko stmf_i_scsi_session_t *iss;
73766ac72a9cSAlexander Stetsenko
73776ac72a9cSAlexander Stetsenko ASSERT(mutex_owned(&stmf_state.stmf_lock));
73786ac72a9cSAlexander Stetsenko
73796ac72a9cSAlexander Stetsenko td = drv_usectohz(20000);
73806ac72a9cSAlexander Stetsenko
7381fcf3ce44SJohn Forte /* Do timeouts */
7382fcf3ce44SJohn Forte if (stmf_state.stmf_nlus &&
7383042f029eSAlexander Stetsenko ((!clks->timing_next) || (ddi_get_lbolt() >= clks->timing_next))) {
7384fcf3ce44SJohn Forte if (!stmf_state.stmf_svc_ilu_timing) {
7385fcf3ce44SJohn Forte /* we are starting a new round */
7386fcf3ce44SJohn Forte stmf_state.stmf_svc_ilu_timing =
7387fcf3ce44SJohn Forte stmf_state.stmf_ilulist;
7388042f029eSAlexander Stetsenko clks->timing_start = ddi_get_lbolt();
7389fcf3ce44SJohn Forte }
73906ac72a9cSAlexander Stetsenko
7391fcf3ce44SJohn Forte stmf_check_ilu_timing();
7392fcf3ce44SJohn Forte if (!stmf_state.stmf_svc_ilu_timing) {
7393fcf3ce44SJohn Forte /* we finished a complete round */
7394042f029eSAlexander Stetsenko clks->timing_next =
7395042f029eSAlexander Stetsenko clks->timing_start + drv_usectohz(5*1000*1000);
7396fcf3ce44SJohn Forte } else {
7397fcf3ce44SJohn Forte /* we still have some ilu items to check */
7398042f029eSAlexander Stetsenko clks->timing_next =
7399fcf3ce44SJohn Forte ddi_get_lbolt() + drv_usectohz(1*1000*1000);
7400fcf3ce44SJohn Forte }
74016ac72a9cSAlexander Stetsenko
7402fcf3ce44SJohn Forte if (stmf_state.stmf_svc_active)
74036ac72a9cSAlexander Stetsenko return;
7404fcf3ce44SJohn Forte }
74056ac72a9cSAlexander Stetsenko
7406fcf3ce44SJohn Forte /* Check if there are free tasks to clear */
7407fcf3ce44SJohn Forte if (stmf_state.stmf_nlus &&
7408042f029eSAlexander Stetsenko ((!clks->drain_next) || (ddi_get_lbolt() >= clks->drain_next))) {
7409fcf3ce44SJohn Forte if (!stmf_state.stmf_svc_ilu_draining) {
7410fcf3ce44SJohn Forte /* we are starting a new round */
7411fcf3ce44SJohn Forte stmf_state.stmf_svc_ilu_draining =
7412fcf3ce44SJohn Forte stmf_state.stmf_ilulist;
7413042f029eSAlexander Stetsenko clks->drain_start = ddi_get_lbolt();
7414fcf3ce44SJohn Forte }
74156ac72a9cSAlexander Stetsenko
7416fcf3ce44SJohn Forte stmf_check_freetask();
7417fcf3ce44SJohn Forte if (!stmf_state.stmf_svc_ilu_draining) {
7418fcf3ce44SJohn Forte /* we finished a complete round */
7419042f029eSAlexander Stetsenko clks->drain_next =
7420042f029eSAlexander Stetsenko clks->drain_start + drv_usectohz(10*1000*1000);
7421fcf3ce44SJohn Forte } else {
7422fcf3ce44SJohn Forte /* we still have some ilu items to check */
7423042f029eSAlexander Stetsenko clks->drain_next =
7424fcf3ce44SJohn Forte ddi_get_lbolt() + drv_usectohz(1*1000*1000);
7425fcf3ce44SJohn Forte }
74266ac72a9cSAlexander Stetsenko
7427fcf3ce44SJohn Forte if (stmf_state.stmf_svc_active)
74286ac72a9cSAlexander Stetsenko return;
7429fcf3ce44SJohn Forte }
7430fcf3ce44SJohn Forte
7431fcf3ce44SJohn Forte /* Check if we need to run worker_mgmt */
7432042f029eSAlexander Stetsenko if (ddi_get_lbolt() > clks->worker_delay) {
7433fcf3ce44SJohn Forte stmf_worker_mgmt();
7434042f029eSAlexander Stetsenko clks->worker_delay = ddi_get_lbolt() +
7435fcf3ce44SJohn Forte stmf_worker_mgmt_delay;
7436fcf3ce44SJohn Forte }
7437fcf3ce44SJohn Forte
7438fcf3ce44SJohn Forte /* Check if any active session got its 1st LUN */
7439fcf3ce44SJohn Forte if (stmf_state.stmf_process_initial_luns) {
7440fcf3ce44SJohn Forte int stmf_level = 0;
7441fcf3ce44SJohn Forte int port_level;
74426ac72a9cSAlexander Stetsenko
7443fcf3ce44SJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport;
7444fcf3ce44SJohn Forte ilport = next_ilport) {
744507377e5eSJohn Forte int ilport_lock_held;
7446fcf3ce44SJohn Forte next_ilport = ilport->ilport_next;
74476ac72a9cSAlexander Stetsenko
7448fcf3ce44SJohn Forte if ((ilport->ilport_flags &
74496ac72a9cSAlexander Stetsenko ILPORT_SS_GOT_INITIAL_LUNS) == 0)
7450fcf3ce44SJohn Forte continue;
74516ac72a9cSAlexander Stetsenko
7452fcf3ce44SJohn Forte port_level = 0;
7453fcf3ce44SJohn Forte rw_enter(&ilport->ilport_lock, RW_READER);
745407377e5eSJohn Forte ilport_lock_held = 1;
74556ac72a9cSAlexander Stetsenko
7456fcf3ce44SJohn Forte for (iss = ilport->ilport_ss_list; iss;
7457fcf3ce44SJohn Forte iss = iss->iss_next) {
7458fcf3ce44SJohn Forte if ((iss->iss_flags &
74596ac72a9cSAlexander Stetsenko ISS_GOT_INITIAL_LUNS) == 0)
7460fcf3ce44SJohn Forte continue;
74616ac72a9cSAlexander Stetsenko
7462fcf3ce44SJohn Forte port_level++;
7463fcf3ce44SJohn Forte stmf_level++;
7464fcf3ce44SJohn Forte atomic_and_32(&iss->iss_flags,
7465fcf3ce44SJohn Forte ~ISS_GOT_INITIAL_LUNS);
7466fcf3ce44SJohn Forte atomic_or_32(&iss->iss_flags,
7467fcf3ce44SJohn Forte ISS_EVENT_ACTIVE);
7468fcf3ce44SJohn Forte rw_exit(&ilport->ilport_lock);
746907377e5eSJohn Forte ilport_lock_held = 0;
7470fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
7471fcf3ce44SJohn Forte stmf_generate_lport_event(ilport,
7472fcf3ce44SJohn Forte LPORT_EVENT_INITIAL_LUN_MAPPED,
7473fcf3ce44SJohn Forte iss->iss_ss, 0);
7474fcf3ce44SJohn Forte atomic_and_32(&iss->iss_flags,
7475fcf3ce44SJohn Forte ~ISS_EVENT_ACTIVE);
7476fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
7477fcf3ce44SJohn Forte /*
7478fcf3ce44SJohn Forte * scan all the ilports again as the
7479fcf3ce44SJohn Forte * ilport list might have changed.
7480fcf3ce44SJohn Forte */
74816ac72a9cSAlexander Stetsenko next_ilport = stmf_state.stmf_ilportlist;
7482fcf3ce44SJohn Forte break;
7483fcf3ce44SJohn Forte }
74846ac72a9cSAlexander Stetsenko
74856ac72a9cSAlexander Stetsenko if (port_level == 0)
7486fcf3ce44SJohn Forte atomic_and_32(&ilport->ilport_flags,
7487fcf3ce44SJohn Forte ~ILPORT_SS_GOT_INITIAL_LUNS);
7488fcf3ce44SJohn Forte /* drop the lock if we are holding it. */
748907377e5eSJohn Forte if (ilport_lock_held == 1)
7490fcf3ce44SJohn Forte rw_exit(&ilport->ilport_lock);
7491fcf3ce44SJohn Forte
7492fcf3ce44SJohn Forte /* Max 4 session at a time */
74936ac72a9cSAlexander Stetsenko if (stmf_level >= 4)
7494fcf3ce44SJohn Forte break;
7495fcf3ce44SJohn Forte }
74966ac72a9cSAlexander Stetsenko
74976ac72a9cSAlexander Stetsenko if (stmf_level == 0)
7498fcf3ce44SJohn Forte stmf_state.stmf_process_initial_luns = 0;
7499fcf3ce44SJohn Forte }
7500fcf3ce44SJohn Forte
7501fcf3ce44SJohn Forte stmf_state.stmf_svc_flags &= ~STMF_SVC_ACTIVE;
7502d3d50737SRafael Vanoni (void) cv_reltimedwait(&stmf_state.stmf_cv,
7503d3d50737SRafael Vanoni &stmf_state.stmf_lock, td, TR_CLOCK_TICK);
7504fcf3ce44SJohn Forte stmf_state.stmf_svc_flags |= STMF_SVC_ACTIVE;
7505fcf3ce44SJohn Forte }
7506fcf3ce44SJohn Forte
7507a49dc893SSaso Kiselkov /*
7508a49dc893SSaso Kiselkov * Waits for ongoing I/O tasks to finish on an LU in preparation for
7509a49dc893SSaso Kiselkov * the LU's offlining. The LU should already be in an Offlining state
7510a49dc893SSaso Kiselkov * (otherwise I/O to the LU might never end). There is an additional
7511a49dc893SSaso Kiselkov * enforcement of this via a deadman timer check.
7512a49dc893SSaso Kiselkov */
7513a49dc893SSaso Kiselkov static void
stmf_wait_ilu_tasks_finish(stmf_i_lu_t * ilu)7514a49dc893SSaso Kiselkov stmf_wait_ilu_tasks_finish(stmf_i_lu_t *ilu)
7515a49dc893SSaso Kiselkov {
7516a49dc893SSaso Kiselkov clock_t start, now, deadline;
7517a49dc893SSaso Kiselkov
7518a49dc893SSaso Kiselkov start = now = ddi_get_lbolt();
7519a49dc893SSaso Kiselkov deadline = start + drv_usectohz(stmf_io_deadman * 1000000llu);
7520a49dc893SSaso Kiselkov mutex_enter(&ilu->ilu_task_lock);
7521a49dc893SSaso Kiselkov while (ilu->ilu_ntasks != ilu->ilu_ntasks_free) {
7522a49dc893SSaso Kiselkov (void) cv_timedwait(&ilu->ilu_offline_pending_cv,
7523a49dc893SSaso Kiselkov &ilu->ilu_task_lock, deadline);
7524a49dc893SSaso Kiselkov now = ddi_get_lbolt();
7525a49dc893SSaso Kiselkov if (now > deadline) {
7526a49dc893SSaso Kiselkov if (stmf_io_deadman_enabled) {
7527a49dc893SSaso Kiselkov cmn_err(CE_PANIC, "stmf_svc: I/O deadman hit "
7528a49dc893SSaso Kiselkov "on STMF_CMD_LU_OFFLINE after %d seconds",
7529a49dc893SSaso Kiselkov stmf_io_deadman);
7530a49dc893SSaso Kiselkov } else {
7531a49dc893SSaso Kiselkov /* keep on spinning */
7532a49dc893SSaso Kiselkov deadline = now + drv_usectohz(stmf_io_deadman *
7533a49dc893SSaso Kiselkov 1000000llu);
7534a49dc893SSaso Kiselkov }
7535a49dc893SSaso Kiselkov }
7536a49dc893SSaso Kiselkov }
7537a49dc893SSaso Kiselkov mutex_exit(&ilu->ilu_task_lock);
7538a49dc893SSaso Kiselkov DTRACE_PROBE1(deadman__timeout__wait, clock_t, now - start);
7539a49dc893SSaso Kiselkov }
7540a49dc893SSaso Kiselkov
7541fcf3ce44SJohn Forte void
stmf_svc_queue(int cmd,void * obj,stmf_state_change_info_t * info)7542fcf3ce44SJohn Forte stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info)
7543fcf3ce44SJohn Forte {
7544fcf3ce44SJohn Forte stmf_svc_req_t *req;
7545fcf3ce44SJohn Forte int s;
7546fcf3ce44SJohn Forte
7547fcf3ce44SJohn Forte ASSERT(!mutex_owned(&stmf_state.stmf_lock));
7548fcf3ce44SJohn Forte s = sizeof (stmf_svc_req_t);
7549fcf3ce44SJohn Forte if (info->st_additional_info) {
7550fcf3ce44SJohn Forte s += strlen(info->st_additional_info) + 1;
7551fcf3ce44SJohn Forte }
7552fcf3ce44SJohn Forte req = kmem_zalloc(s, KM_SLEEP);
7553fcf3ce44SJohn Forte
7554fcf3ce44SJohn Forte req->svc_cmd = cmd;
7555fcf3ce44SJohn Forte req->svc_obj = obj;
7556fcf3ce44SJohn Forte req->svc_info.st_rflags = info->st_rflags;
7557fcf3ce44SJohn Forte if (info->st_additional_info) {
7558fcf3ce44SJohn Forte req->svc_info.st_additional_info = (char *)(GET_BYTE_OFFSET(req,
7559fcf3ce44SJohn Forte sizeof (stmf_svc_req_t)));
7560fcf3ce44SJohn Forte (void) strcpy(req->svc_info.st_additional_info,
7561fcf3ce44SJohn Forte info->st_additional_info);
7562fcf3ce44SJohn Forte }
7563fcf3ce44SJohn Forte req->svc_req_alloc_size = s;
75646ac72a9cSAlexander Stetsenko req->svc_next = NULL;
7565fcf3ce44SJohn Forte
7566fcf3ce44SJohn Forte mutex_enter(&stmf_state.stmf_lock);
75676ac72a9cSAlexander Stetsenko *stmf_state.stmf_svc_tailp = req;
75686ac72a9cSAlexander Stetsenko stmf_state.stmf_svc_tailp = &req->svc_next;
7569fcf3ce44SJohn Forte if ((stmf_state.stmf_svc_flags & STMF_SVC_ACTIVE) == 0) {
7570fcf3ce44SJohn Forte cv_signal(&stmf_state.stmf_cv);
7571fcf3ce44SJohn Forte }
7572fcf3ce44SJohn Forte mutex_exit(&stmf_state.stmf_lock);
7573fcf3ce44SJohn Forte }
7574fcf3ce44SJohn Forte
75756ac72a9cSAlexander Stetsenko static void
stmf_svc_kill_obj_requests(void * obj)75766ac72a9cSAlexander Stetsenko stmf_svc_kill_obj_requests(void *obj)
75776ac72a9cSAlexander Stetsenko {
75786ac72a9cSAlexander Stetsenko stmf_svc_req_t *prev_req = NULL;
75796ac72a9cSAlexander Stetsenko stmf_svc_req_t *next_req;
75806ac72a9cSAlexander Stetsenko stmf_svc_req_t *req;
75816ac72a9cSAlexander Stetsenko
75826ac72a9cSAlexander Stetsenko ASSERT(mutex_owned(&stmf_state.stmf_lock));
75836ac72a9cSAlexander Stetsenko
75846ac72a9cSAlexander Stetsenko for (req = stmf_state.stmf_svc_active; req != NULL; req = next_req) {
75856ac72a9cSAlexander Stetsenko next_req = req->svc_next;
75866ac72a9cSAlexander Stetsenko
75876ac72a9cSAlexander Stetsenko if (req->svc_obj == obj) {
75886ac72a9cSAlexander Stetsenko if (prev_req != NULL)
75896ac72a9cSAlexander Stetsenko prev_req->svc_next = next_req;
75906ac72a9cSAlexander Stetsenko else
75916ac72a9cSAlexander Stetsenko stmf_state.stmf_svc_active = next_req;
75926ac72a9cSAlexander Stetsenko
75936ac72a9cSAlexander Stetsenko if (next_req == NULL)
75946ac72a9cSAlexander Stetsenko stmf_state.stmf_svc_tailp = (prev_req != NULL) ?
75956ac72a9cSAlexander Stetsenko &prev_req->svc_next :
75966ac72a9cSAlexander Stetsenko &stmf_state.stmf_svc_active;
75976ac72a9cSAlexander Stetsenko
75986ac72a9cSAlexander Stetsenko kmem_free(req, req->svc_req_alloc_size);
75996ac72a9cSAlexander Stetsenko } else {
76006ac72a9cSAlexander Stetsenko prev_req = req;
76016ac72a9cSAlexander Stetsenko }
76026ac72a9cSAlexander Stetsenko }
76036ac72a9cSAlexander Stetsenko }
76046ac72a9cSAlexander Stetsenko
7605fcf3ce44SJohn Forte void
stmf_trace(caddr_t ident,const char * fmt,...)7606fcf3ce44SJohn Forte stmf_trace(caddr_t ident, const char *fmt, ...)
7607fcf3ce44SJohn Forte {
7608fcf3ce44SJohn Forte va_list args;
7609fcf3ce44SJohn Forte char tbuf[160];
7610fcf3ce44SJohn Forte int len;
7611fcf3ce44SJohn Forte
7612fcf3ce44SJohn Forte if (!stmf_trace_on)
7613fcf3ce44SJohn Forte return;
7614fcf3ce44SJohn Forte len = snprintf(tbuf, 158, "%s:%07lu: ", ident ? ident : "",
7615fcf3ce44SJohn Forte ddi_get_lbolt());
7616fcf3ce44SJohn Forte va_start(args, fmt);
7617fcf3ce44SJohn Forte len += vsnprintf(tbuf + len, 158 - len, fmt, args);
7618fcf3ce44SJohn Forte va_end(args);
7619fcf3ce44SJohn Forte
7620fcf3ce44SJohn Forte if (len > 158) {
7621fcf3ce44SJohn Forte len = 158;
7622fcf3ce44SJohn Forte }
7623fcf3ce44SJohn Forte tbuf[len++] = '\n';
7624fcf3ce44SJohn Forte tbuf[len] = 0;
7625fcf3ce44SJohn Forte
7626fcf3ce44SJohn Forte mutex_enter(&trace_buf_lock);
7627fcf3ce44SJohn Forte bcopy(tbuf, &stmf_trace_buf[trace_buf_curndx], len+1);
7628fcf3ce44SJohn Forte trace_buf_curndx += len;
7629fcf3ce44SJohn Forte if (trace_buf_curndx > (trace_buf_size - 320))
7630fcf3ce44SJohn Forte trace_buf_curndx = 0;
7631fcf3ce44SJohn Forte mutex_exit(&trace_buf_lock);
7632fcf3ce44SJohn Forte }
7633fcf3ce44SJohn Forte
7634fcf3ce44SJohn Forte void
stmf_trace_clear()7635fcf3ce44SJohn Forte stmf_trace_clear()
7636fcf3ce44SJohn Forte {
7637fcf3ce44SJohn Forte if (!stmf_trace_on)
7638fcf3ce44SJohn Forte return;
7639fcf3ce44SJohn Forte mutex_enter(&trace_buf_lock);
7640fcf3ce44SJohn Forte trace_buf_curndx = 0;
7641fcf3ce44SJohn Forte if (trace_buf_size > 0)
7642fcf3ce44SJohn Forte stmf_trace_buf[0] = 0;
7643fcf3ce44SJohn Forte mutex_exit(&trace_buf_lock);
7644fcf3ce44SJohn Forte }
7645fcf3ce44SJohn Forte
7646fcf3ce44SJohn Forte static void
stmf_abort_task_offline(scsi_task_t * task,int offline_lu,char * info)7647fcf3ce44SJohn Forte stmf_abort_task_offline(scsi_task_t *task, int offline_lu, char *info)
7648fcf3ce44SJohn Forte {
7649fcf3ce44SJohn Forte stmf_state_change_info_t change_info;
7650fcf3ce44SJohn Forte void *ctl_private;
7651fcf3ce44SJohn Forte uint32_t ctl_cmd;
7652fcf3ce44SJohn Forte int msg = 0;
7653fcf3ce44SJohn Forte
7654fcf3ce44SJohn Forte stmf_trace("FROM STMF", "abort_task_offline called for %s: %s",
7655fcf3ce44SJohn Forte offline_lu ? "LU" : "LPORT", info ? info : "no additional info");
7656fcf3ce44SJohn Forte change_info.st_additional_info = info;
7657fcf3ce44SJohn Forte if (offline_lu) {
7658fcf3ce44SJohn Forte change_info.st_rflags = STMF_RFLAG_RESET |
7659fcf3ce44SJohn Forte STMF_RFLAG_LU_ABORT;
7660fcf3ce44SJohn Forte ctl_private = task->task_lu;
7661fcf3ce44SJohn Forte if (((stmf_i_lu_t *)
7662fcf3ce44SJohn Forte task->task_lu->lu_stmf_private)->ilu_state ==
7663fcf3ce44SJohn Forte STMF_STATE_ONLINE) {
7664fcf3ce44SJohn Forte msg = 1;
7665fcf3ce44SJohn Forte }
7666fcf3ce44SJohn Forte ctl_cmd = STMF_CMD_LU_OFFLINE;
7667fcf3ce44SJohn Forte } else {
7668fcf3ce44SJohn Forte change_info.st_rflags = STMF_RFLAG_RESET |
7669fcf3ce44SJohn Forte STMF_RFLAG_LPORT_ABORT;
7670fcf3ce44SJohn Forte ctl_private = task->task_lport;
7671fcf3ce44SJohn Forte if (((stmf_i_local_port_t *)
7672fcf3ce44SJohn Forte task->task_lport->lport_stmf_private)->ilport_state ==
7673fcf3ce44SJohn Forte STMF_STATE_ONLINE) {
7674fcf3ce44SJohn Forte msg = 1;
7675fcf3ce44SJohn Forte }
7676fcf3ce44SJohn Forte ctl_cmd = STMF_CMD_LPORT_OFFLINE;
7677fcf3ce44SJohn Forte }
7678fcf3ce44SJohn Forte
7679fcf3ce44SJohn Forte if (msg) {
7680fcf3ce44SJohn Forte stmf_trace(0, "Calling stmf_ctl to offline %s : %s",
7681fcf3ce44SJohn Forte offline_lu ? "LU" : "LPORT", info ? info :
7682fcf3ce44SJohn Forte "<no additional info>");
7683fcf3ce44SJohn Forte }
7684fcf3ce44SJohn Forte (void) stmf_ctl(ctl_cmd, ctl_private, &change_info);
7685fcf3ce44SJohn Forte }
7686716c1805SNattuvetty Bhavyan
7687716c1805SNattuvetty Bhavyan static char
stmf_ctoi(char c)7688716c1805SNattuvetty Bhavyan stmf_ctoi(char c)
7689716c1805SNattuvetty Bhavyan {
7690716c1805SNattuvetty Bhavyan if ((c >= '0') && (c <= '9'))
7691716c1805SNattuvetty Bhavyan c -= '0';
7692716c1805SNattuvetty Bhavyan else if ((c >= 'A') && (c <= 'F'))
7693716c1805SNattuvetty Bhavyan c = c - 'A' + 10;
7694716c1805SNattuvetty Bhavyan else if ((c >= 'a') && (c <= 'f'))
7695716c1805SNattuvetty Bhavyan c = c - 'a' + 10;
7696716c1805SNattuvetty Bhavyan else
7697716c1805SNattuvetty Bhavyan c = -1;
7698716c1805SNattuvetty Bhavyan return (c);
7699716c1805SNattuvetty Bhavyan }
7700716c1805SNattuvetty Bhavyan
7701716c1805SNattuvetty Bhavyan /* Convert from Hex value in ASCII format to the equivalent bytes */
7702716c1805SNattuvetty Bhavyan static boolean_t
stmf_base16_str_to_binary(char * c,int dplen,uint8_t * dp)7703716c1805SNattuvetty Bhavyan stmf_base16_str_to_binary(char *c, int dplen, uint8_t *dp)
7704716c1805SNattuvetty Bhavyan {
7705716c1805SNattuvetty Bhavyan int ii;
7706716c1805SNattuvetty Bhavyan
7707716c1805SNattuvetty Bhavyan for (ii = 0; ii < dplen; ii++) {
7708716c1805SNattuvetty Bhavyan char nibble1, nibble2;
7709716c1805SNattuvetty Bhavyan char enc_char = *c++;
7710716c1805SNattuvetty Bhavyan nibble1 = stmf_ctoi(enc_char);
7711716c1805SNattuvetty Bhavyan
7712716c1805SNattuvetty Bhavyan enc_char = *c++;
7713716c1805SNattuvetty Bhavyan nibble2 = stmf_ctoi(enc_char);
7714716c1805SNattuvetty Bhavyan if (nibble1 == -1 || nibble2 == -1)
7715716c1805SNattuvetty Bhavyan return (B_FALSE);
7716716c1805SNattuvetty Bhavyan
7717716c1805SNattuvetty Bhavyan dp[ii] = (nibble1 << 4) | nibble2;
7718716c1805SNattuvetty Bhavyan }
7719716c1805SNattuvetty Bhavyan return (B_TRUE);
7720716c1805SNattuvetty Bhavyan }
7721716c1805SNattuvetty Bhavyan
7722716c1805SNattuvetty Bhavyan boolean_t
stmf_scsilib_tptid_validate(scsi_transport_id_t * tptid,uint32_t total_sz,uint16_t * tptid_sz)7723716c1805SNattuvetty Bhavyan stmf_scsilib_tptid_validate(scsi_transport_id_t *tptid, uint32_t total_sz,
7724716c1805SNattuvetty Bhavyan uint16_t *tptid_sz)
7725716c1805SNattuvetty Bhavyan {
7726716c1805SNattuvetty Bhavyan uint16_t tpd_len = SCSI_TPTID_SIZE;
7727716c1805SNattuvetty Bhavyan
7728716c1805SNattuvetty Bhavyan if (tptid_sz)
7729716c1805SNattuvetty Bhavyan *tptid_sz = 0;
7730716c1805SNattuvetty Bhavyan if (total_sz < sizeof (scsi_transport_id_t))
7731716c1805SNattuvetty Bhavyan return (B_FALSE);
7732716c1805SNattuvetty Bhavyan
7733716c1805SNattuvetty Bhavyan switch (tptid->protocol_id) {
7734716c1805SNattuvetty Bhavyan
7735716c1805SNattuvetty Bhavyan case PROTOCOL_FIBRE_CHANNEL:
7736716c1805SNattuvetty Bhavyan /* FC Transport ID validation checks. SPC3 rev23, Table 284 */
7737716c1805SNattuvetty Bhavyan if (total_sz < tpd_len || tptid->format_code != 0)
7738716c1805SNattuvetty Bhavyan return (B_FALSE);
7739716c1805SNattuvetty Bhavyan break;
7740716c1805SNattuvetty Bhavyan
7741716c1805SNattuvetty Bhavyan case PROTOCOL_iSCSI:
7742716c1805SNattuvetty Bhavyan {
7743716c1805SNattuvetty Bhavyan iscsi_transport_id_t *iscsiid;
7744716c1805SNattuvetty Bhavyan uint16_t adn_len, name_len;
7745716c1805SNattuvetty Bhavyan
7746716c1805SNattuvetty Bhavyan /* Check for valid format code, SPC3 rev 23 Table 288 */
7747716c1805SNattuvetty Bhavyan if ((total_sz < tpd_len) ||
7748716c1805SNattuvetty Bhavyan (tptid->format_code != 0 && tptid->format_code != 1))
7749716c1805SNattuvetty Bhavyan return (B_FALSE);
7750716c1805SNattuvetty Bhavyan
7751716c1805SNattuvetty Bhavyan iscsiid = (iscsi_transport_id_t *)tptid;
7752716c1805SNattuvetty Bhavyan adn_len = READ_SCSI16(iscsiid->add_len, uint16_t);
7753716c1805SNattuvetty Bhavyan tpd_len = sizeof (iscsi_transport_id_t) + adn_len - 1;
7754716c1805SNattuvetty Bhavyan
7755716c1805SNattuvetty Bhavyan /*
7756716c1805SNattuvetty Bhavyan * iSCSI Transport ID validation checks.
7757716c1805SNattuvetty Bhavyan * As per SPC3 rev 23 Section 7.5.4.6 and Table 289 & Table 290
7758716c1805SNattuvetty Bhavyan */
7759716c1805SNattuvetty Bhavyan if (adn_len < 20 || (adn_len % 4 != 0))
7760716c1805SNattuvetty Bhavyan return (B_FALSE);
7761716c1805SNattuvetty Bhavyan
7762716c1805SNattuvetty Bhavyan name_len = strnlen(iscsiid->iscsi_name, adn_len);
7763716c1805SNattuvetty Bhavyan if (name_len == 0 || name_len >= adn_len)
7764716c1805SNattuvetty Bhavyan return (B_FALSE);
7765716c1805SNattuvetty Bhavyan
7766716c1805SNattuvetty Bhavyan /* If the format_code is 1 check for ISID seperator */
7767716c1805SNattuvetty Bhavyan if ((tptid->format_code == 1) && (strstr(iscsiid->iscsi_name,
7768716c1805SNattuvetty Bhavyan SCSI_TPTID_ISCSI_ISID_SEPERATOR) == NULL))
7769716c1805SNattuvetty Bhavyan return (B_FALSE);
7770716c1805SNattuvetty Bhavyan
7771716c1805SNattuvetty Bhavyan }
7772716c1805SNattuvetty Bhavyan break;
7773716c1805SNattuvetty Bhavyan
7774716c1805SNattuvetty Bhavyan case PROTOCOL_SRP:
7775716c1805SNattuvetty Bhavyan /* SRP Transport ID validation checks. SPC3 rev23, Table 287 */
7776716c1805SNattuvetty Bhavyan if (total_sz < tpd_len || tptid->format_code != 0)
7777716c1805SNattuvetty Bhavyan return (B_FALSE);
7778716c1805SNattuvetty Bhavyan break;
7779716c1805SNattuvetty Bhavyan
7780716c1805SNattuvetty Bhavyan case PROTOCOL_PARALLEL_SCSI:
7781716c1805SNattuvetty Bhavyan case PROTOCOL_SSA:
7782716c1805SNattuvetty Bhavyan case PROTOCOL_IEEE_1394:
7783716c1805SNattuvetty Bhavyan case PROTOCOL_SAS:
7784716c1805SNattuvetty Bhavyan case PROTOCOL_ADT:
7785716c1805SNattuvetty Bhavyan case PROTOCOL_ATAPI:
7786716c1805SNattuvetty Bhavyan default:
7787716c1805SNattuvetty Bhavyan {
7788716c1805SNattuvetty Bhavyan stmf_dflt_scsi_tptid_t *dflttpd;
7789716c1805SNattuvetty Bhavyan
7790716c1805SNattuvetty Bhavyan tpd_len = sizeof (stmf_dflt_scsi_tptid_t);
7791716c1805SNattuvetty Bhavyan if (total_sz < tpd_len)
7792716c1805SNattuvetty Bhavyan return (B_FALSE);
7793716c1805SNattuvetty Bhavyan dflttpd = (stmf_dflt_scsi_tptid_t *)tptid;
7794716c1805SNattuvetty Bhavyan tpd_len = tpd_len + SCSI_READ16(&dflttpd->ident_len) - 1;
7795716c1805SNattuvetty Bhavyan if (total_sz < tpd_len)
7796716c1805SNattuvetty Bhavyan return (B_FALSE);
7797716c1805SNattuvetty Bhavyan }
7798716c1805SNattuvetty Bhavyan break;
7799716c1805SNattuvetty Bhavyan }
7800716c1805SNattuvetty Bhavyan if (tptid_sz)
7801716c1805SNattuvetty Bhavyan *tptid_sz = tpd_len;
7802716c1805SNattuvetty Bhavyan return (B_TRUE);
7803716c1805SNattuvetty Bhavyan }
7804716c1805SNattuvetty Bhavyan
7805716c1805SNattuvetty Bhavyan boolean_t
stmf_scsilib_tptid_compare(scsi_transport_id_t * tpd1,scsi_transport_id_t * tpd2)7806716c1805SNattuvetty Bhavyan stmf_scsilib_tptid_compare(scsi_transport_id_t *tpd1,
7807716c1805SNattuvetty Bhavyan scsi_transport_id_t *tpd2)
7808716c1805SNattuvetty Bhavyan {
7809716c1805SNattuvetty Bhavyan if ((tpd1->protocol_id != tpd2->protocol_id) ||
7810716c1805SNattuvetty Bhavyan (tpd1->format_code != tpd2->format_code))
7811716c1805SNattuvetty Bhavyan return (B_FALSE);
7812716c1805SNattuvetty Bhavyan
7813716c1805SNattuvetty Bhavyan switch (tpd1->protocol_id) {
7814716c1805SNattuvetty Bhavyan
7815716c1805SNattuvetty Bhavyan case PROTOCOL_iSCSI:
7816716c1805SNattuvetty Bhavyan {
7817716c1805SNattuvetty Bhavyan iscsi_transport_id_t *iscsitpd1, *iscsitpd2;
7818716c1805SNattuvetty Bhavyan uint16_t len;
7819716c1805SNattuvetty Bhavyan
7820716c1805SNattuvetty Bhavyan iscsitpd1 = (iscsi_transport_id_t *)tpd1;
7821716c1805SNattuvetty Bhavyan iscsitpd2 = (iscsi_transport_id_t *)tpd2;
7822716c1805SNattuvetty Bhavyan len = SCSI_READ16(&iscsitpd1->add_len);
7823716c1805SNattuvetty Bhavyan if ((memcmp(iscsitpd1->add_len, iscsitpd2->add_len, 2) != 0) ||
7824716c1805SNattuvetty Bhavyan (memcmp(iscsitpd1->iscsi_name, iscsitpd2->iscsi_name, len)
7825716c1805SNattuvetty Bhavyan != 0))
7826716c1805SNattuvetty Bhavyan return (B_FALSE);
7827716c1805SNattuvetty Bhavyan }
7828716c1805SNattuvetty Bhavyan break;
7829716c1805SNattuvetty Bhavyan
7830716c1805SNattuvetty Bhavyan case PROTOCOL_SRP:
7831716c1805SNattuvetty Bhavyan {
7832716c1805SNattuvetty Bhavyan scsi_srp_transport_id_t *srptpd1, *srptpd2;
7833716c1805SNattuvetty Bhavyan
7834716c1805SNattuvetty Bhavyan srptpd1 = (scsi_srp_transport_id_t *)tpd1;
7835716c1805SNattuvetty Bhavyan srptpd2 = (scsi_srp_transport_id_t *)tpd2;
7836716c1805SNattuvetty Bhavyan if (memcmp(srptpd1->srp_name, srptpd2->srp_name,
7837716c1805SNattuvetty Bhavyan sizeof (srptpd1->srp_name)) != 0)
7838716c1805SNattuvetty Bhavyan return (B_FALSE);
7839716c1805SNattuvetty Bhavyan }
7840716c1805SNattuvetty Bhavyan break;
7841716c1805SNattuvetty Bhavyan
7842716c1805SNattuvetty Bhavyan case PROTOCOL_FIBRE_CHANNEL:
7843716c1805SNattuvetty Bhavyan {
7844716c1805SNattuvetty Bhavyan scsi_fc_transport_id_t *fctpd1, *fctpd2;
7845716c1805SNattuvetty Bhavyan
7846716c1805SNattuvetty Bhavyan fctpd1 = (scsi_fc_transport_id_t *)tpd1;
7847716c1805SNattuvetty Bhavyan fctpd2 = (scsi_fc_transport_id_t *)tpd2;
7848716c1805SNattuvetty Bhavyan if (memcmp(fctpd1->port_name, fctpd2->port_name,
7849716c1805SNattuvetty Bhavyan sizeof (fctpd1->port_name)) != 0)
7850716c1805SNattuvetty Bhavyan return (B_FALSE);
7851716c1805SNattuvetty Bhavyan }
7852716c1805SNattuvetty Bhavyan break;
7853716c1805SNattuvetty Bhavyan
7854716c1805SNattuvetty Bhavyan case PROTOCOL_PARALLEL_SCSI:
7855716c1805SNattuvetty Bhavyan case PROTOCOL_SSA:
7856716c1805SNattuvetty Bhavyan case PROTOCOL_IEEE_1394:
7857716c1805SNattuvetty Bhavyan case PROTOCOL_SAS:
7858716c1805SNattuvetty Bhavyan case PROTOCOL_ADT:
7859716c1805SNattuvetty Bhavyan case PROTOCOL_ATAPI:
7860716c1805SNattuvetty Bhavyan default:
7861716c1805SNattuvetty Bhavyan {
7862716c1805SNattuvetty Bhavyan stmf_dflt_scsi_tptid_t *dflt1, *dflt2;
7863716c1805SNattuvetty Bhavyan uint16_t len;
7864716c1805SNattuvetty Bhavyan
7865716c1805SNattuvetty Bhavyan dflt1 = (stmf_dflt_scsi_tptid_t *)tpd1;
7866716c1805SNattuvetty Bhavyan dflt2 = (stmf_dflt_scsi_tptid_t *)tpd2;
7867716c1805SNattuvetty Bhavyan len = SCSI_READ16(&dflt1->ident_len);
7868716c1805SNattuvetty Bhavyan if ((memcmp(dflt1->ident_len, dflt2->ident_len, 2) != 0) ||
7869716c1805SNattuvetty Bhavyan (memcmp(dflt1->ident, dflt2->ident, len) != 0))
7870716c1805SNattuvetty Bhavyan return (B_FALSE);
7871716c1805SNattuvetty Bhavyan }
7872716c1805SNattuvetty Bhavyan break;
7873716c1805SNattuvetty Bhavyan }
7874716c1805SNattuvetty Bhavyan return (B_TRUE);
7875716c1805SNattuvetty Bhavyan }
7876716c1805SNattuvetty Bhavyan
7877716c1805SNattuvetty Bhavyan /*
7878716c1805SNattuvetty Bhavyan * Changes devid_desc to corresponding TransportID format
7879716c1805SNattuvetty Bhavyan * Returns :- pointer to stmf_remote_port_t
7880716c1805SNattuvetty Bhavyan * Note :- Allocates continous memory for stmf_remote_port_t and TransportID,
7881716c1805SNattuvetty Bhavyan * This memory need to be freed when this remote_port is no longer
7882716c1805SNattuvetty Bhavyan * used.
7883716c1805SNattuvetty Bhavyan */
7884716c1805SNattuvetty Bhavyan stmf_remote_port_t *
stmf_scsilib_devid_to_remote_port(scsi_devid_desc_t * devid)7885716c1805SNattuvetty Bhavyan stmf_scsilib_devid_to_remote_port(scsi_devid_desc_t *devid)
7886716c1805SNattuvetty Bhavyan {
7887716c1805SNattuvetty Bhavyan struct scsi_fc_transport_id *fc_tpd;
7888716c1805SNattuvetty Bhavyan struct iscsi_transport_id *iscsi_tpd;
7889716c1805SNattuvetty Bhavyan struct scsi_srp_transport_id *srp_tpd;
7890716c1805SNattuvetty Bhavyan struct stmf_dflt_scsi_tptid *dflt_tpd;
7891716c1805SNattuvetty Bhavyan uint16_t ident_len, sz = 0;
7892716c1805SNattuvetty Bhavyan stmf_remote_port_t *rpt = NULL;
7893716c1805SNattuvetty Bhavyan
7894716c1805SNattuvetty Bhavyan ident_len = devid->ident_length;
7895716c1805SNattuvetty Bhavyan ASSERT(ident_len);
7896716c1805SNattuvetty Bhavyan switch (devid->protocol_id) {
7897716c1805SNattuvetty Bhavyan case PROTOCOL_FIBRE_CHANNEL:
7898716c1805SNattuvetty Bhavyan sz = sizeof (scsi_fc_transport_id_t);
7899716c1805SNattuvetty Bhavyan rpt = stmf_remote_port_alloc(sz);
7900716c1805SNattuvetty Bhavyan rpt->rport_tptid->format_code = 0;
7901716c1805SNattuvetty Bhavyan rpt->rport_tptid->protocol_id = devid->protocol_id;
7902716c1805SNattuvetty Bhavyan fc_tpd = (scsi_fc_transport_id_t *)rpt->rport_tptid;
7903716c1805SNattuvetty Bhavyan /*
7904716c1805SNattuvetty Bhavyan * convert from "wwn.xxxxxxxxxxxxxxxx" to 8-byte binary
7905716c1805SNattuvetty Bhavyan * skip first 4 byte for "wwn."
7906716c1805SNattuvetty Bhavyan */
7907716c1805SNattuvetty Bhavyan ASSERT(strncmp("wwn.", (char *)devid->ident, 4) == 0);
7908716c1805SNattuvetty Bhavyan if ((ident_len < SCSI_TPTID_FC_PORT_NAME_SIZE * 2 + 4) ||
7909716c1805SNattuvetty Bhavyan !stmf_base16_str_to_binary((char *)devid->ident + 4,
7910716c1805SNattuvetty Bhavyan SCSI_TPTID_FC_PORT_NAME_SIZE, fc_tpd->port_name))
7911716c1805SNattuvetty Bhavyan goto devid_to_remote_port_fail;
7912716c1805SNattuvetty Bhavyan break;
7913716c1805SNattuvetty Bhavyan
7914716c1805SNattuvetty Bhavyan case PROTOCOL_iSCSI:
7915716c1805SNattuvetty Bhavyan sz = ALIGNED_TO_8BYTE_BOUNDARY(sizeof (iscsi_transport_id_t) +
7916716c1805SNattuvetty Bhavyan ident_len - 1);
7917716c1805SNattuvetty Bhavyan rpt = stmf_remote_port_alloc(sz);
7918716c1805SNattuvetty Bhavyan rpt->rport_tptid->format_code = 0;
7919716c1805SNattuvetty Bhavyan rpt->rport_tptid->protocol_id = devid->protocol_id;
7920716c1805SNattuvetty Bhavyan iscsi_tpd = (iscsi_transport_id_t *)rpt->rport_tptid;
7921716c1805SNattuvetty Bhavyan SCSI_WRITE16(iscsi_tpd->add_len, ident_len);
7922716c1805SNattuvetty Bhavyan (void) memcpy(iscsi_tpd->iscsi_name, devid->ident, ident_len);
7923716c1805SNattuvetty Bhavyan break;
7924716c1805SNattuvetty Bhavyan
7925716c1805SNattuvetty Bhavyan case PROTOCOL_SRP:
7926716c1805SNattuvetty Bhavyan sz = sizeof (scsi_srp_transport_id_t);
7927716c1805SNattuvetty Bhavyan rpt = stmf_remote_port_alloc(sz);
7928716c1805SNattuvetty Bhavyan rpt->rport_tptid->format_code = 0;
7929716c1805SNattuvetty Bhavyan rpt->rport_tptid->protocol_id = devid->protocol_id;
7930716c1805SNattuvetty Bhavyan srp_tpd = (scsi_srp_transport_id_t *)rpt->rport_tptid;
7931716c1805SNattuvetty Bhavyan /*
7932716c1805SNattuvetty Bhavyan * convert from "eui.xxxxxxxxxxxxxxx" to 8-byte binary
7933716c1805SNattuvetty Bhavyan * skip first 4 byte for "eui."
7934716c1805SNattuvetty Bhavyan * Assume 8-byte initiator-extension part of srp_name is NOT
7935716c1805SNattuvetty Bhavyan * stored in devid and hence will be set as zero
7936716c1805SNattuvetty Bhavyan */
7937716c1805SNattuvetty Bhavyan ASSERT(strncmp("eui.", (char *)devid->ident, 4) == 0);
7938716c1805SNattuvetty Bhavyan if ((ident_len < (SCSI_TPTID_SRP_PORT_NAME_LEN - 8) * 2 + 4) ||
7939716c1805SNattuvetty Bhavyan !stmf_base16_str_to_binary((char *)devid->ident+4,
7940716c1805SNattuvetty Bhavyan SCSI_TPTID_SRP_PORT_NAME_LEN, srp_tpd->srp_name))
7941716c1805SNattuvetty Bhavyan goto devid_to_remote_port_fail;
7942716c1805SNattuvetty Bhavyan break;
7943716c1805SNattuvetty Bhavyan
7944716c1805SNattuvetty Bhavyan case PROTOCOL_PARALLEL_SCSI:
7945716c1805SNattuvetty Bhavyan case PROTOCOL_SSA:
7946716c1805SNattuvetty Bhavyan case PROTOCOL_IEEE_1394:
7947716c1805SNattuvetty Bhavyan case PROTOCOL_SAS:
7948716c1805SNattuvetty Bhavyan case PROTOCOL_ADT:
7949716c1805SNattuvetty Bhavyan case PROTOCOL_ATAPI:
7950716c1805SNattuvetty Bhavyan default :
7951716c1805SNattuvetty Bhavyan ident_len = devid->ident_length;
7952716c1805SNattuvetty Bhavyan sz = ALIGNED_TO_8BYTE_BOUNDARY(sizeof (stmf_dflt_scsi_tptid_t) +
7953716c1805SNattuvetty Bhavyan ident_len - 1);
7954716c1805SNattuvetty Bhavyan rpt = stmf_remote_port_alloc(sz);
7955716c1805SNattuvetty Bhavyan rpt->rport_tptid->format_code = 0;
7956716c1805SNattuvetty Bhavyan rpt->rport_tptid->protocol_id = devid->protocol_id;
7957716c1805SNattuvetty Bhavyan dflt_tpd = (stmf_dflt_scsi_tptid_t *)rpt->rport_tptid;
7958716c1805SNattuvetty Bhavyan SCSI_WRITE16(dflt_tpd->ident_len, ident_len);
7959716c1805SNattuvetty Bhavyan (void) memcpy(dflt_tpd->ident, devid->ident, ident_len);
7960716c1805SNattuvetty Bhavyan break;
7961716c1805SNattuvetty Bhavyan }
7962716c1805SNattuvetty Bhavyan return (rpt);
7963716c1805SNattuvetty Bhavyan
7964716c1805SNattuvetty Bhavyan devid_to_remote_port_fail:
7965716c1805SNattuvetty Bhavyan stmf_remote_port_free(rpt);
7966716c1805SNattuvetty Bhavyan return (NULL);
7967716c1805SNattuvetty Bhavyan
7968716c1805SNattuvetty Bhavyan }
7969716c1805SNattuvetty Bhavyan
7970716c1805SNattuvetty Bhavyan stmf_remote_port_t *
stmf_remote_port_alloc(uint16_t tptid_sz)7971716c1805SNattuvetty Bhavyan stmf_remote_port_alloc(uint16_t tptid_sz) {
7972716c1805SNattuvetty Bhavyan stmf_remote_port_t *rpt;
7973716c1805SNattuvetty Bhavyan rpt = (stmf_remote_port_t *)kmem_zalloc(
7974716c1805SNattuvetty Bhavyan sizeof (stmf_remote_port_t) + tptid_sz, KM_SLEEP);
7975716c1805SNattuvetty Bhavyan rpt->rport_tptid_sz = tptid_sz;
7976716c1805SNattuvetty Bhavyan rpt->rport_tptid = (scsi_transport_id_t *)(rpt + 1);
7977716c1805SNattuvetty Bhavyan return (rpt);
7978716c1805SNattuvetty Bhavyan }
7979716c1805SNattuvetty Bhavyan
7980716c1805SNattuvetty Bhavyan void
stmf_remote_port_free(stmf_remote_port_t * rpt)7981716c1805SNattuvetty Bhavyan stmf_remote_port_free(stmf_remote_port_t *rpt)
7982716c1805SNattuvetty Bhavyan {
7983716c1805SNattuvetty Bhavyan /*
7984716c1805SNattuvetty Bhavyan * Note: stmf_scsilib_devid_to_remote_port() function allocates
7985716c1805SNattuvetty Bhavyan * remote port structures for all transports in the same way, So
7986716c1805SNattuvetty Bhavyan * it is safe to deallocate it in a protocol independent manner.
7987716c1805SNattuvetty Bhavyan * If any of the allocation method changes, corresponding changes
7988716c1805SNattuvetty Bhavyan * need to be made here too.
7989716c1805SNattuvetty Bhavyan */
7990716c1805SNattuvetty Bhavyan kmem_free(rpt, sizeof (stmf_remote_port_t) + rpt->rport_tptid_sz);
7991716c1805SNattuvetty Bhavyan }
7992