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