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