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