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