1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/conf.h> 26 #include <sys/file.h> 27 #include <sys/ddi.h> 28 #include <sys/sunddi.h> 29 #include <sys/modctl.h> 30 #include <sys/scsi/scsi.h> 31 #include <sys/scsi/impl/scsi_reset_notify.h> 32 #include <sys/disp.h> 33 #include <sys/byteorder.h> 34 #include <sys/atomic.h> 35 #include <sys/ethernet.h> 36 #include <sys/sdt.h> 37 #include <sys/nvpair.h> 38 #include <sys/zone.h> 39 #include <sys/id_space.h> 40 41 #include <sys/stmf.h> 42 #include <sys/lpif.h> 43 #include <sys/portif.h> 44 #include <sys/stmf_ioctl.h> 45 #include <sys/pppt_ic_if.h> 46 47 #include "stmf_impl.h" 48 #include "lun_map.h" 49 #include "stmf_state.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, int set_rel_off); 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 dbuf->db_relative_offset = task->task_nbytes_transferred; 1827 stmf_xd_to_dbuf(dbuf, 0); 1828 1829 dbuf->db_flags = DB_DIRECTION_TO_RPORT; 1830 (void) stmf_xfer_data(task, dbuf, 0); 1831 return (STMF_SUCCESS); 1832 } 1833 1834 stmf_status_t 1835 stmf_proxy_scsi_cmd(scsi_task_t *task, stmf_data_buf_t *dbuf) 1836 { 1837 stmf_i_scsi_task_t *itask = 1838 (stmf_i_scsi_task_t *)task->task_stmf_private; 1839 stmf_i_local_port_t *ilport = 1840 (stmf_i_local_port_t *)task->task_lport->lport_stmf_private; 1841 stmf_ic_msg_t *ic_cmd_msg; 1842 stmf_ic_msg_status_t ic_ret; 1843 stmf_status_t ret = STMF_FAILURE; 1844 1845 if (stmf_state.stmf_alua_state != 1) { 1846 cmn_err(CE_WARN, "stmf alua state is disabled"); 1847 return (STMF_FAILURE); 1848 } 1849 1850 if (ilport->ilport_proxy_registered == 0) { 1851 return (STMF_FAILURE); 1852 } 1853 1854 mutex_enter(&stmf_state.stmf_lock); 1855 itask->itask_proxy_msg_id = stmf_proxy_msg_id++; 1856 mutex_exit(&stmf_state.stmf_lock); 1857 itask->itask_proxy_dbuf = dbuf; 1858 1859 /* 1860 * stmf will now take over the task handling for this task 1861 * but it still needs to be treated differently from other 1862 * default handled tasks, hence the ITASK_PROXY_TASK. 1863 * If this is a task management function, we're really just 1864 * duping the command to the peer. Set the TM bit so that 1865 * we can recognize this on return since we won't be completing 1866 * the proxied task in that case. 1867 */ 1868 if (task->task_mgmt_function) { 1869 itask->itask_proxy_msg_id |= MSG_ID_TM_BIT; 1870 } else { 1871 uint32_t new, old; 1872 do { 1873 new = old = itask->itask_flags; 1874 if (new & ITASK_BEING_ABORTED) 1875 return (STMF_FAILURE); 1876 new |= ITASK_DEFAULT_HANDLING | ITASK_PROXY_TASK; 1877 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 1878 } 1879 if (dbuf) { 1880 ic_cmd_msg = ic_scsi_cmd_msg_alloc(itask->itask_proxy_msg_id, 1881 task, dbuf->db_data_size, dbuf->db_sglist[0].seg_addr, 1882 itask->itask_proxy_msg_id); 1883 } else { 1884 ic_cmd_msg = ic_scsi_cmd_msg_alloc(itask->itask_proxy_msg_id, 1885 task, 0, NULL, itask->itask_proxy_msg_id); 1886 } 1887 if (ic_cmd_msg) { 1888 ic_ret = ic_tx_msg(ic_cmd_msg); 1889 if (ic_ret == STMF_IC_MSG_SUCCESS) { 1890 ret = STMF_SUCCESS; 1891 } 1892 } 1893 return (ret); 1894 } 1895 1896 1897 stmf_status_t 1898 pppt_modload() 1899 { 1900 int error; 1901 1902 if (pppt_mod == NULL && ((pppt_mod = 1903 ddi_modopen("drv/pppt", KRTLD_MODE_FIRST, &error)) == NULL)) { 1904 cmn_err(CE_WARN, "Unable to load pppt"); 1905 return (STMF_FAILURE); 1906 } 1907 1908 if (ic_reg_port_msg_alloc == NULL && ((ic_reg_port_msg_alloc = 1909 (stmf_ic_reg_port_msg_alloc_func_t) 1910 ddi_modsym(pppt_mod, "stmf_ic_reg_port_msg_alloc", 1911 &error)) == NULL)) { 1912 cmn_err(CE_WARN, 1913 "Unable to find symbol - stmf_ic_reg_port_msg_alloc"); 1914 return (STMF_FAILURE); 1915 } 1916 1917 1918 if (ic_dereg_port_msg_alloc == NULL && ((ic_dereg_port_msg_alloc = 1919 (stmf_ic_dereg_port_msg_alloc_func_t) 1920 ddi_modsym(pppt_mod, "stmf_ic_dereg_port_msg_alloc", 1921 &error)) == NULL)) { 1922 cmn_err(CE_WARN, 1923 "Unable to find symbol - stmf_ic_dereg_port_msg_alloc"); 1924 return (STMF_FAILURE); 1925 } 1926 1927 if (ic_reg_lun_msg_alloc == NULL && ((ic_reg_lun_msg_alloc = 1928 (stmf_ic_reg_lun_msg_alloc_func_t) 1929 ddi_modsym(pppt_mod, "stmf_ic_reg_lun_msg_alloc", 1930 &error)) == NULL)) { 1931 cmn_err(CE_WARN, 1932 "Unable to find symbol - stmf_ic_reg_lun_msg_alloc"); 1933 return (STMF_FAILURE); 1934 } 1935 1936 if (ic_lun_active_msg_alloc == NULL && ((ic_lun_active_msg_alloc = 1937 (stmf_ic_lun_active_msg_alloc_func_t) 1938 ddi_modsym(pppt_mod, "stmf_ic_lun_active_msg_alloc", 1939 &error)) == NULL)) { 1940 cmn_err(CE_WARN, 1941 "Unable to find symbol - stmf_ic_lun_active_msg_alloc"); 1942 return (STMF_FAILURE); 1943 } 1944 1945 if (ic_dereg_lun_msg_alloc == NULL && ((ic_dereg_lun_msg_alloc = 1946 (stmf_ic_dereg_lun_msg_alloc_func_t) 1947 ddi_modsym(pppt_mod, "stmf_ic_dereg_lun_msg_alloc", 1948 &error)) == NULL)) { 1949 cmn_err(CE_WARN, 1950 "Unable to find symbol - stmf_ic_dereg_lun_msg_alloc"); 1951 return (STMF_FAILURE); 1952 } 1953 1954 if (ic_scsi_cmd_msg_alloc == NULL && ((ic_scsi_cmd_msg_alloc = 1955 (stmf_ic_scsi_cmd_msg_alloc_func_t) 1956 ddi_modsym(pppt_mod, "stmf_ic_scsi_cmd_msg_alloc", 1957 &error)) == NULL)) { 1958 cmn_err(CE_WARN, 1959 "Unable to find symbol - stmf_ic_scsi_cmd_msg_alloc"); 1960 return (STMF_FAILURE); 1961 } 1962 1963 if (ic_scsi_data_xfer_done_msg_alloc == NULL && 1964 ((ic_scsi_data_xfer_done_msg_alloc = 1965 (stmf_ic_scsi_data_xfer_done_msg_alloc_func_t) 1966 ddi_modsym(pppt_mod, "stmf_ic_scsi_data_xfer_done_msg_alloc", 1967 &error)) == NULL)) { 1968 cmn_err(CE_WARN, 1969 "Unable to find symbol -" 1970 "stmf_ic_scsi_data_xfer_done_msg_alloc"); 1971 return (STMF_FAILURE); 1972 } 1973 1974 if (ic_session_reg_msg_alloc == NULL && 1975 ((ic_session_reg_msg_alloc = 1976 (stmf_ic_session_create_msg_alloc_func_t) 1977 ddi_modsym(pppt_mod, "stmf_ic_session_create_msg_alloc", 1978 &error)) == NULL)) { 1979 cmn_err(CE_WARN, 1980 "Unable to find symbol -" 1981 "stmf_ic_session_create_msg_alloc"); 1982 return (STMF_FAILURE); 1983 } 1984 1985 if (ic_session_dereg_msg_alloc == NULL && 1986 ((ic_session_dereg_msg_alloc = 1987 (stmf_ic_session_destroy_msg_alloc_func_t) 1988 ddi_modsym(pppt_mod, "stmf_ic_session_destroy_msg_alloc", 1989 &error)) == NULL)) { 1990 cmn_err(CE_WARN, 1991 "Unable to find symbol -" 1992 "stmf_ic_session_destroy_msg_alloc"); 1993 return (STMF_FAILURE); 1994 } 1995 1996 if (ic_tx_msg == NULL && ((ic_tx_msg = 1997 (stmf_ic_tx_msg_func_t)ddi_modsym(pppt_mod, "stmf_ic_tx_msg", 1998 &error)) == NULL)) { 1999 cmn_err(CE_WARN, "Unable to find symbol - stmf_ic_tx_msg"); 2000 return (STMF_FAILURE); 2001 } 2002 2003 if (ic_msg_free == NULL && ((ic_msg_free = 2004 (stmf_ic_msg_free_func_t)ddi_modsym(pppt_mod, "stmf_ic_msg_free", 2005 &error)) == NULL)) { 2006 cmn_err(CE_WARN, "Unable to find symbol - stmf_ic_msg_free"); 2007 return (STMF_FAILURE); 2008 } 2009 return (STMF_SUCCESS); 2010 } 2011 2012 static void 2013 stmf_get_alua_state(stmf_alua_state_desc_t *alua_state) 2014 { 2015 mutex_enter(&stmf_state.stmf_lock); 2016 alua_state->alua_node = stmf_state.stmf_alua_node; 2017 alua_state->alua_state = stmf_state.stmf_alua_state; 2018 mutex_exit(&stmf_state.stmf_lock); 2019 } 2020 2021 2022 static int 2023 stmf_set_alua_state(stmf_alua_state_desc_t *alua_state) 2024 { 2025 stmf_i_local_port_t *ilport; 2026 stmf_i_lu_t *ilu; 2027 stmf_lu_t *lu; 2028 stmf_ic_msg_status_t ic_ret; 2029 stmf_ic_msg_t *ic_reg_lun, *ic_reg_port; 2030 stmf_local_port_t *lport; 2031 int ret = 0; 2032 2033 if (alua_state->alua_state > 1 || alua_state->alua_node > 1) { 2034 return (EINVAL); 2035 } 2036 2037 mutex_enter(&stmf_state.stmf_lock); 2038 if (alua_state->alua_state == 1) { 2039 if (pppt_modload() == STMF_FAILURE) { 2040 ret = EIO; 2041 goto err; 2042 } 2043 if (alua_state->alua_node != 0) { 2044 /* reset existing rtpids to new base */ 2045 stmf_rtpid_counter = 255; 2046 } 2047 stmf_state.stmf_alua_node = alua_state->alua_node; 2048 stmf_state.stmf_alua_state = 1; 2049 /* register existing local ports with ppp */ 2050 for (ilport = stmf_state.stmf_ilportlist; ilport != NULL; 2051 ilport = ilport->ilport_next) { 2052 /* skip standby ports and non-alua participants */ 2053 if (ilport->ilport_standby == 1 || 2054 ilport->ilport_alua == 0) { 2055 continue; 2056 } 2057 if (alua_state->alua_node != 0) { 2058 ilport->ilport_rtpid = 2059 atomic_add_16_nv(&stmf_rtpid_counter, 1); 2060 } 2061 lport = ilport->ilport_lport; 2062 ic_reg_port = ic_reg_port_msg_alloc( 2063 lport->lport_id, ilport->ilport_rtpid, 2064 0, NULL, stmf_proxy_msg_id); 2065 if (ic_reg_port) { 2066 ic_ret = ic_tx_msg(ic_reg_port); 2067 if (ic_ret == STMF_IC_MSG_SUCCESS) { 2068 ilport->ilport_reg_msgid = 2069 stmf_proxy_msg_id++; 2070 } else { 2071 cmn_err(CE_WARN, 2072 "error on port registration " 2073 "port - %s", 2074 ilport->ilport_kstat_tgt_name); 2075 } 2076 } 2077 } 2078 /* register existing logical units */ 2079 for (ilu = stmf_state.stmf_ilulist; ilu != NULL; 2080 ilu = ilu->ilu_next) { 2081 if (ilu->ilu_access != STMF_LU_ACTIVE) { 2082 continue; 2083 } 2084 /* register with proxy module */ 2085 lu = ilu->ilu_lu; 2086 if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 && 2087 lu->lu_lp->lp_alua_support) { 2088 ilu->ilu_alua = 1; 2089 /* allocate the register message */ 2090 ic_reg_lun = ic_reg_lun_msg_alloc( 2091 lu->lu_id->ident, lu->lu_lp->lp_name, 2092 lu->lu_proxy_reg_arg_len, 2093 (uint8_t *)lu->lu_proxy_reg_arg, 2094 stmf_proxy_msg_id); 2095 /* send the message */ 2096 if (ic_reg_lun) { 2097 ic_ret = ic_tx_msg(ic_reg_lun); 2098 if (ic_ret == STMF_IC_MSG_SUCCESS) { 2099 stmf_proxy_msg_id++; 2100 } 2101 } 2102 } 2103 } 2104 } else { 2105 stmf_state.stmf_alua_state = 0; 2106 } 2107 2108 err: 2109 mutex_exit(&stmf_state.stmf_lock); 2110 return (ret); 2111 } 2112 2113 2114 typedef struct { 2115 void *bp; /* back pointer from internal struct to main struct */ 2116 int alloc_size; 2117 } __istmf_t; 2118 2119 typedef struct { 2120 __istmf_t *fp; /* Framework private */ 2121 void *cp; /* Caller private */ 2122 void *ss; /* struct specific */ 2123 } __stmf_t; 2124 2125 static struct { 2126 int shared; 2127 int fw_private; 2128 } stmf_sizes[] = { { 0, 0 }, 2129 { GET_STRUCT_SIZE(stmf_lu_provider_t), 2130 GET_STRUCT_SIZE(stmf_i_lu_provider_t) }, 2131 { GET_STRUCT_SIZE(stmf_port_provider_t), 2132 GET_STRUCT_SIZE(stmf_i_port_provider_t) }, 2133 { GET_STRUCT_SIZE(stmf_local_port_t), 2134 GET_STRUCT_SIZE(stmf_i_local_port_t) }, 2135 { GET_STRUCT_SIZE(stmf_lu_t), 2136 GET_STRUCT_SIZE(stmf_i_lu_t) }, 2137 { GET_STRUCT_SIZE(stmf_scsi_session_t), 2138 GET_STRUCT_SIZE(stmf_i_scsi_session_t) }, 2139 { GET_STRUCT_SIZE(scsi_task_t), 2140 GET_STRUCT_SIZE(stmf_i_scsi_task_t) }, 2141 { GET_STRUCT_SIZE(stmf_data_buf_t), 2142 GET_STRUCT_SIZE(__istmf_t) }, 2143 { GET_STRUCT_SIZE(stmf_dbuf_store_t), 2144 GET_STRUCT_SIZE(__istmf_t) } 2145 2146 }; 2147 2148 void * 2149 stmf_alloc(stmf_struct_id_t struct_id, int additional_size, int flags) 2150 { 2151 int stmf_size; 2152 int kmem_flag; 2153 __stmf_t *sh; 2154 2155 if ((struct_id == 0) || (struct_id >= STMF_MAX_STRUCT_IDS)) 2156 return (NULL); 2157 2158 if ((curthread->t_flag & T_INTR_THREAD) || (flags & AF_FORCE_NOSLEEP)) { 2159 kmem_flag = KM_NOSLEEP; 2160 } else { 2161 kmem_flag = KM_SLEEP; 2162 } 2163 2164 additional_size = (additional_size + 7) & (~7); 2165 stmf_size = stmf_sizes[struct_id].shared + 2166 stmf_sizes[struct_id].fw_private + additional_size; 2167 2168 if (flags & AF_DONTZERO) 2169 sh = (__stmf_t *)kmem_alloc(stmf_size, kmem_flag); 2170 else 2171 sh = (__stmf_t *)kmem_zalloc(stmf_size, kmem_flag); 2172 2173 if (sh == NULL) 2174 return (NULL); 2175 2176 /* 2177 * In principle, the implementation inside stmf_alloc should not 2178 * be changed anyway. But the original order of framework private 2179 * data and caller private data does not support sglist in the caller 2180 * private data. 2181 * To work around this, the memory segments of framework private 2182 * data and caller private data are re-ordered here. 2183 * A better solution is to provide a specific interface to allocate 2184 * the sglist, then we will not need this workaround any more. 2185 * But before the new interface is available, the memory segment 2186 * ordering should be kept as is. 2187 */ 2188 sh->cp = GET_BYTE_OFFSET(sh, stmf_sizes[struct_id].shared); 2189 sh->fp = (__istmf_t *)GET_BYTE_OFFSET(sh, 2190 stmf_sizes[struct_id].shared + additional_size); 2191 2192 sh->fp->bp = sh; 2193 /* Just store the total size instead of storing additional size */ 2194 sh->fp->alloc_size = stmf_size; 2195 2196 return (sh); 2197 } 2198 2199 void 2200 stmf_free(void *ptr) 2201 { 2202 __stmf_t *sh = (__stmf_t *)ptr; 2203 2204 /* 2205 * So far we dont need any struct specific processing. If such 2206 * a need ever arises, then store the struct id in the framework 2207 * private section and get it here as sh->fp->struct_id. 2208 */ 2209 kmem_free(ptr, sh->fp->alloc_size); 2210 } 2211 2212 /* 2213 * Given a pointer to stmf_lu_t, verifies if this lu is registered with the 2214 * framework and returns a pointer to framework private data for the lu. 2215 * Returns NULL if the lu was not found. 2216 */ 2217 stmf_i_lu_t * 2218 stmf_lookup_lu(stmf_lu_t *lu) 2219 { 2220 stmf_i_lu_t *ilu; 2221 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 2222 2223 for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) { 2224 if (ilu->ilu_lu == lu) 2225 return (ilu); 2226 } 2227 return (NULL); 2228 } 2229 2230 /* 2231 * Given a pointer to stmf_local_port_t, verifies if this lport is registered 2232 * with the framework and returns a pointer to framework private data for 2233 * the lport. 2234 * Returns NULL if the lport was not found. 2235 */ 2236 stmf_i_local_port_t * 2237 stmf_lookup_lport(stmf_local_port_t *lport) 2238 { 2239 stmf_i_local_port_t *ilport; 2240 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 2241 2242 for (ilport = stmf_state.stmf_ilportlist; ilport != NULL; 2243 ilport = ilport->ilport_next) { 2244 if (ilport->ilport_lport == lport) 2245 return (ilport); 2246 } 2247 return (NULL); 2248 } 2249 2250 stmf_status_t 2251 stmf_register_lu_provider(stmf_lu_provider_t *lp) 2252 { 2253 stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private; 2254 stmf_pp_data_t *ppd; 2255 uint32_t cb_flags; 2256 2257 if (lp->lp_lpif_rev != LPIF_REV_1 && lp->lp_lpif_rev != LPIF_REV_2) 2258 return (STMF_FAILURE); 2259 2260 mutex_enter(&stmf_state.stmf_lock); 2261 ilp->ilp_next = stmf_state.stmf_ilplist; 2262 stmf_state.stmf_ilplist = ilp; 2263 stmf_state.stmf_nlps++; 2264 2265 /* See if we need to do a callback */ 2266 for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) { 2267 if (strcmp(ppd->ppd_name, lp->lp_name) == 0) { 2268 break; 2269 } 2270 } 2271 if ((ppd == NULL) || (ppd->ppd_nv == NULL)) { 2272 goto rlp_bail_out; 2273 } 2274 ilp->ilp_ppd = ppd; 2275 ppd->ppd_provider = ilp; 2276 if (lp->lp_cb == NULL) 2277 goto rlp_bail_out; 2278 ilp->ilp_cb_in_progress = 1; 2279 cb_flags = STMF_PCB_PREG_COMPLETE; 2280 if (stmf_state.stmf_config_state == STMF_CONFIG_INIT) 2281 cb_flags |= STMF_PCB_STMF_ONLINING; 2282 mutex_exit(&stmf_state.stmf_lock); 2283 lp->lp_cb(lp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags); 2284 mutex_enter(&stmf_state.stmf_lock); 2285 ilp->ilp_cb_in_progress = 0; 2286 2287 rlp_bail_out: 2288 mutex_exit(&stmf_state.stmf_lock); 2289 2290 return (STMF_SUCCESS); 2291 } 2292 2293 stmf_status_t 2294 stmf_deregister_lu_provider(stmf_lu_provider_t *lp) 2295 { 2296 stmf_i_lu_provider_t **ppilp; 2297 stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private; 2298 2299 mutex_enter(&stmf_state.stmf_lock); 2300 if (ilp->ilp_nlus || ilp->ilp_cb_in_progress) { 2301 mutex_exit(&stmf_state.stmf_lock); 2302 return (STMF_BUSY); 2303 } 2304 for (ppilp = &stmf_state.stmf_ilplist; *ppilp != NULL; 2305 ppilp = &((*ppilp)->ilp_next)) { 2306 if (*ppilp == ilp) { 2307 *ppilp = ilp->ilp_next; 2308 stmf_state.stmf_nlps--; 2309 if (ilp->ilp_ppd) { 2310 ilp->ilp_ppd->ppd_provider = NULL; 2311 ilp->ilp_ppd = NULL; 2312 } 2313 mutex_exit(&stmf_state.stmf_lock); 2314 return (STMF_SUCCESS); 2315 } 2316 } 2317 mutex_exit(&stmf_state.stmf_lock); 2318 return (STMF_NOT_FOUND); 2319 } 2320 2321 stmf_status_t 2322 stmf_register_port_provider(stmf_port_provider_t *pp) 2323 { 2324 stmf_i_port_provider_t *ipp = 2325 (stmf_i_port_provider_t *)pp->pp_stmf_private; 2326 stmf_pp_data_t *ppd; 2327 uint32_t cb_flags; 2328 2329 if (pp->pp_portif_rev != PORTIF_REV_1) 2330 return (STMF_FAILURE); 2331 2332 mutex_enter(&stmf_state.stmf_lock); 2333 ipp->ipp_next = stmf_state.stmf_ipplist; 2334 stmf_state.stmf_ipplist = ipp; 2335 stmf_state.stmf_npps++; 2336 /* See if we need to do a callback */ 2337 for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) { 2338 if (strcmp(ppd->ppd_name, pp->pp_name) == 0) { 2339 break; 2340 } 2341 } 2342 if ((ppd == NULL) || (ppd->ppd_nv == NULL)) { 2343 goto rpp_bail_out; 2344 } 2345 ipp->ipp_ppd = ppd; 2346 ppd->ppd_provider = ipp; 2347 if (pp->pp_cb == NULL) 2348 goto rpp_bail_out; 2349 ipp->ipp_cb_in_progress = 1; 2350 cb_flags = STMF_PCB_PREG_COMPLETE; 2351 if (stmf_state.stmf_config_state == STMF_CONFIG_INIT) 2352 cb_flags |= STMF_PCB_STMF_ONLINING; 2353 mutex_exit(&stmf_state.stmf_lock); 2354 pp->pp_cb(pp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags); 2355 mutex_enter(&stmf_state.stmf_lock); 2356 ipp->ipp_cb_in_progress = 0; 2357 2358 rpp_bail_out: 2359 mutex_exit(&stmf_state.stmf_lock); 2360 2361 return (STMF_SUCCESS); 2362 } 2363 2364 stmf_status_t 2365 stmf_deregister_port_provider(stmf_port_provider_t *pp) 2366 { 2367 stmf_i_port_provider_t *ipp = 2368 (stmf_i_port_provider_t *)pp->pp_stmf_private; 2369 stmf_i_port_provider_t **ppipp; 2370 2371 mutex_enter(&stmf_state.stmf_lock); 2372 if (ipp->ipp_npps || ipp->ipp_cb_in_progress) { 2373 mutex_exit(&stmf_state.stmf_lock); 2374 return (STMF_BUSY); 2375 } 2376 for (ppipp = &stmf_state.stmf_ipplist; *ppipp != NULL; 2377 ppipp = &((*ppipp)->ipp_next)) { 2378 if (*ppipp == ipp) { 2379 *ppipp = ipp->ipp_next; 2380 stmf_state.stmf_npps--; 2381 if (ipp->ipp_ppd) { 2382 ipp->ipp_ppd->ppd_provider = NULL; 2383 ipp->ipp_ppd = NULL; 2384 } 2385 mutex_exit(&stmf_state.stmf_lock); 2386 return (STMF_SUCCESS); 2387 } 2388 } 2389 mutex_exit(&stmf_state.stmf_lock); 2390 return (STMF_NOT_FOUND); 2391 } 2392 2393 int 2394 stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token, 2395 uint32_t *err_ret) 2396 { 2397 stmf_i_port_provider_t *ipp; 2398 stmf_i_lu_provider_t *ilp; 2399 stmf_pp_data_t *ppd; 2400 nvlist_t *nv; 2401 int s; 2402 int ret; 2403 2404 *err_ret = 0; 2405 2406 if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) { 2407 return (EINVAL); 2408 } 2409 2410 mutex_enter(&stmf_state.stmf_lock); 2411 for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) { 2412 if (ppi->ppi_lu_provider) { 2413 if (!ppd->ppd_lu_provider) 2414 continue; 2415 } else if (ppi->ppi_port_provider) { 2416 if (!ppd->ppd_port_provider) 2417 continue; 2418 } 2419 if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0) 2420 break; 2421 } 2422 2423 if (ppd == NULL) { 2424 /* New provider */ 2425 s = strlen(ppi->ppi_name); 2426 if (s > 254) { 2427 mutex_exit(&stmf_state.stmf_lock); 2428 return (EINVAL); 2429 } 2430 s += sizeof (stmf_pp_data_t) - 7; 2431 2432 ppd = kmem_zalloc(s, KM_NOSLEEP); 2433 if (ppd == NULL) { 2434 mutex_exit(&stmf_state.stmf_lock); 2435 return (ENOMEM); 2436 } 2437 ppd->ppd_alloc_size = s; 2438 (void) strcpy(ppd->ppd_name, ppi->ppi_name); 2439 2440 /* See if this provider already exists */ 2441 if (ppi->ppi_lu_provider) { 2442 ppd->ppd_lu_provider = 1; 2443 for (ilp = stmf_state.stmf_ilplist; ilp != NULL; 2444 ilp = ilp->ilp_next) { 2445 if (strcmp(ppi->ppi_name, 2446 ilp->ilp_lp->lp_name) == 0) { 2447 ppd->ppd_provider = ilp; 2448 ilp->ilp_ppd = ppd; 2449 break; 2450 } 2451 } 2452 } else { 2453 ppd->ppd_port_provider = 1; 2454 for (ipp = stmf_state.stmf_ipplist; ipp != NULL; 2455 ipp = ipp->ipp_next) { 2456 if (strcmp(ppi->ppi_name, 2457 ipp->ipp_pp->pp_name) == 0) { 2458 ppd->ppd_provider = ipp; 2459 ipp->ipp_ppd = ppd; 2460 break; 2461 } 2462 } 2463 } 2464 2465 /* Link this ppd in */ 2466 ppd->ppd_next = stmf_state.stmf_ppdlist; 2467 stmf_state.stmf_ppdlist = ppd; 2468 } 2469 2470 /* 2471 * User is requesting that the token be checked. 2472 * If there was another set after the user's get 2473 * it's an error 2474 */ 2475 if (ppi->ppi_token_valid) { 2476 if (ppi->ppi_token != ppd->ppd_token) { 2477 *err_ret = STMF_IOCERR_PPD_UPDATED; 2478 mutex_exit(&stmf_state.stmf_lock); 2479 return (EINVAL); 2480 } 2481 } 2482 2483 if ((ret = nvlist_unpack((char *)ppi->ppi_data, 2484 (size_t)ppi->ppi_data_size, &nv, KM_NOSLEEP)) != 0) { 2485 mutex_exit(&stmf_state.stmf_lock); 2486 return (ret); 2487 } 2488 2489 /* Free any existing lists and add this one to the ppd */ 2490 if (ppd->ppd_nv) 2491 nvlist_free(ppd->ppd_nv); 2492 ppd->ppd_nv = nv; 2493 2494 /* set the token for writes */ 2495 ppd->ppd_token++; 2496 /* return token to caller */ 2497 if (ppi_token) { 2498 *ppi_token = ppd->ppd_token; 2499 } 2500 2501 /* If there is a provider registered, do the notifications */ 2502 if (ppd->ppd_provider) { 2503 uint32_t cb_flags = 0; 2504 2505 if (stmf_state.stmf_config_state == STMF_CONFIG_INIT) 2506 cb_flags |= STMF_PCB_STMF_ONLINING; 2507 if (ppi->ppi_lu_provider) { 2508 ilp = (stmf_i_lu_provider_t *)ppd->ppd_provider; 2509 if (ilp->ilp_lp->lp_cb == NULL) 2510 goto bail_out; 2511 ilp->ilp_cb_in_progress = 1; 2512 mutex_exit(&stmf_state.stmf_lock); 2513 ilp->ilp_lp->lp_cb(ilp->ilp_lp, 2514 STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags); 2515 mutex_enter(&stmf_state.stmf_lock); 2516 ilp->ilp_cb_in_progress = 0; 2517 } else { 2518 ipp = (stmf_i_port_provider_t *)ppd->ppd_provider; 2519 if (ipp->ipp_pp->pp_cb == NULL) 2520 goto bail_out; 2521 ipp->ipp_cb_in_progress = 1; 2522 mutex_exit(&stmf_state.stmf_lock); 2523 ipp->ipp_pp->pp_cb(ipp->ipp_pp, 2524 STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags); 2525 mutex_enter(&stmf_state.stmf_lock); 2526 ipp->ipp_cb_in_progress = 0; 2527 } 2528 } 2529 2530 bail_out: 2531 mutex_exit(&stmf_state.stmf_lock); 2532 2533 return (0); 2534 } 2535 2536 void 2537 stmf_delete_ppd(stmf_pp_data_t *ppd) 2538 { 2539 stmf_pp_data_t **pppd; 2540 2541 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 2542 if (ppd->ppd_provider) { 2543 if (ppd->ppd_lu_provider) { 2544 ((stmf_i_lu_provider_t *) 2545 ppd->ppd_provider)->ilp_ppd = NULL; 2546 } else { 2547 ((stmf_i_port_provider_t *) 2548 ppd->ppd_provider)->ipp_ppd = NULL; 2549 } 2550 ppd->ppd_provider = NULL; 2551 } 2552 2553 for (pppd = &stmf_state.stmf_ppdlist; *pppd != NULL; 2554 pppd = &((*pppd)->ppd_next)) { 2555 if (*pppd == ppd) 2556 break; 2557 } 2558 2559 if (*pppd == NULL) 2560 return; 2561 2562 *pppd = ppd->ppd_next; 2563 if (ppd->ppd_nv) 2564 nvlist_free(ppd->ppd_nv); 2565 2566 kmem_free(ppd, ppd->ppd_alloc_size); 2567 } 2568 2569 int 2570 stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi) 2571 { 2572 stmf_pp_data_t *ppd; 2573 int ret = ENOENT; 2574 2575 if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) { 2576 return (EINVAL); 2577 } 2578 2579 mutex_enter(&stmf_state.stmf_lock); 2580 2581 for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) { 2582 if (ppi->ppi_lu_provider) { 2583 if (!ppd->ppd_lu_provider) 2584 continue; 2585 } else if (ppi->ppi_port_provider) { 2586 if (!ppd->ppd_port_provider) 2587 continue; 2588 } 2589 if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0) 2590 break; 2591 } 2592 2593 if (ppd) { 2594 ret = 0; 2595 stmf_delete_ppd(ppd); 2596 } 2597 mutex_exit(&stmf_state.stmf_lock); 2598 2599 return (ret); 2600 } 2601 2602 int 2603 stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out, 2604 uint32_t *err_ret) 2605 { 2606 stmf_pp_data_t *ppd; 2607 size_t req_size; 2608 int ret = ENOENT; 2609 char *bufp = (char *)ppi_out->ppi_data; 2610 2611 if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) { 2612 return (EINVAL); 2613 } 2614 2615 mutex_enter(&stmf_state.stmf_lock); 2616 2617 for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) { 2618 if (ppi->ppi_lu_provider) { 2619 if (!ppd->ppd_lu_provider) 2620 continue; 2621 } else if (ppi->ppi_port_provider) { 2622 if (!ppd->ppd_port_provider) 2623 continue; 2624 } 2625 if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0) 2626 break; 2627 } 2628 2629 if (ppd && ppd->ppd_nv) { 2630 ppi_out->ppi_token = ppd->ppd_token; 2631 if ((ret = nvlist_size(ppd->ppd_nv, &req_size, 2632 NV_ENCODE_XDR)) != 0) { 2633 goto done; 2634 } 2635 ppi_out->ppi_data_size = req_size; 2636 if (req_size > ppi->ppi_data_size) { 2637 *err_ret = STMF_IOCERR_INSUFFICIENT_BUF; 2638 ret = EINVAL; 2639 goto done; 2640 } 2641 2642 if ((ret = nvlist_pack(ppd->ppd_nv, &bufp, &req_size, 2643 NV_ENCODE_XDR, 0)) != 0) { 2644 goto done; 2645 } 2646 ret = 0; 2647 } 2648 2649 done: 2650 mutex_exit(&stmf_state.stmf_lock); 2651 2652 return (ret); 2653 } 2654 2655 void 2656 stmf_delete_all_ppds() 2657 { 2658 stmf_pp_data_t *ppd, *nppd; 2659 2660 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 2661 for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = nppd) { 2662 nppd = ppd->ppd_next; 2663 stmf_delete_ppd(ppd); 2664 } 2665 } 2666 2667 /* 2668 * 16 is the max string length of a protocol_ident, increase 2669 * the size if needed. 2670 */ 2671 #define STMF_KSTAT_LU_SZ (STMF_GUID_INPUT + 1 + 256) 2672 #define STMF_KSTAT_TGT_SZ (256 * 2 + 16) 2673 2674 /* 2675 * This array matches the Protocol Identifier in stmf_ioctl.h 2676 */ 2677 #define MAX_PROTO_STR_LEN 32 2678 2679 char *protocol_ident[PROTOCOL_ANY] = { 2680 "Fibre Channel", 2681 "Parallel SCSI", 2682 "SSA", 2683 "IEEE_1394", 2684 "SRP", 2685 "iSCSI", 2686 "SAS", 2687 "ADT", 2688 "ATAPI", 2689 "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN" 2690 }; 2691 2692 /* 2693 * Update the lun wait/run queue count 2694 */ 2695 static void 2696 stmf_update_kstat_lu_q(scsi_task_t *task, void func()) 2697 { 2698 stmf_i_lu_t *ilu; 2699 kstat_io_t *kip; 2700 2701 if (task->task_lu == dlun0) 2702 return; 2703 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 2704 if (ilu != NULL && ilu->ilu_kstat_io != NULL) { 2705 kip = KSTAT_IO_PTR(ilu->ilu_kstat_io); 2706 if (kip != NULL) { 2707 func(kip); 2708 } 2709 } 2710 } 2711 2712 /* 2713 * Update the target(lport) wait/run queue count 2714 */ 2715 static void 2716 stmf_update_kstat_lport_q(scsi_task_t *task, void func()) 2717 { 2718 stmf_i_local_port_t *ilp; 2719 kstat_io_t *kip; 2720 2721 ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private; 2722 if (ilp != NULL && ilp->ilport_kstat_io != NULL) { 2723 kip = KSTAT_IO_PTR(ilp->ilport_kstat_io); 2724 if (kip != NULL) { 2725 mutex_enter(ilp->ilport_kstat_io->ks_lock); 2726 func(kip); 2727 mutex_exit(ilp->ilport_kstat_io->ks_lock); 2728 } 2729 } 2730 } 2731 2732 static void 2733 stmf_update_kstat_lport_io(scsi_task_t *task, stmf_data_buf_t *dbuf) 2734 { 2735 stmf_i_local_port_t *ilp; 2736 kstat_io_t *kip; 2737 2738 ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private; 2739 if (ilp != NULL && ilp->ilport_kstat_io != NULL) { 2740 kip = KSTAT_IO_PTR(ilp->ilport_kstat_io); 2741 if (kip != NULL) { 2742 mutex_enter(ilp->ilport_kstat_io->ks_lock); 2743 STMF_UPDATE_KSTAT_IO(kip, dbuf); 2744 mutex_exit(ilp->ilport_kstat_io->ks_lock); 2745 } 2746 } 2747 } 2748 2749 static void 2750 stmf_update_kstat_lu_io(scsi_task_t *task, stmf_data_buf_t *dbuf) 2751 { 2752 stmf_i_lu_t *ilu; 2753 kstat_io_t *kip; 2754 2755 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 2756 if (ilu != NULL && ilu->ilu_kstat_io != NULL) { 2757 kip = KSTAT_IO_PTR(ilu->ilu_kstat_io); 2758 if (kip != NULL) { 2759 mutex_enter(ilu->ilu_kstat_io->ks_lock); 2760 STMF_UPDATE_KSTAT_IO(kip, dbuf); 2761 mutex_exit(ilu->ilu_kstat_io->ks_lock); 2762 } 2763 } 2764 } 2765 2766 static void 2767 stmf_create_kstat_lu(stmf_i_lu_t *ilu) 2768 { 2769 char ks_nm[KSTAT_STRLEN]; 2770 stmf_kstat_lu_info_t *ks_lu; 2771 2772 /* create kstat lun info */ 2773 ks_lu = (stmf_kstat_lu_info_t *)kmem_zalloc(STMF_KSTAT_LU_SZ, 2774 KM_NOSLEEP); 2775 if (ks_lu == NULL) { 2776 cmn_err(CE_WARN, "STMF: kmem_zalloc failed"); 2777 return; 2778 } 2779 2780 bzero(ks_nm, sizeof (ks_nm)); 2781 (void) sprintf(ks_nm, "stmf_lu_%"PRIxPTR"", (uintptr_t)ilu); 2782 if ((ilu->ilu_kstat_info = kstat_create(STMF_MODULE_NAME, 0, 2783 ks_nm, "misc", KSTAT_TYPE_NAMED, 2784 sizeof (stmf_kstat_lu_info_t) / sizeof (kstat_named_t), 2785 KSTAT_FLAG_VIRTUAL)) == NULL) { 2786 kmem_free(ks_lu, STMF_KSTAT_LU_SZ); 2787 cmn_err(CE_WARN, "STMF: kstat_create lu failed"); 2788 return; 2789 } 2790 2791 ilu->ilu_kstat_info->ks_data_size = STMF_KSTAT_LU_SZ; 2792 ilu->ilu_kstat_info->ks_data = ks_lu; 2793 2794 kstat_named_init(&ks_lu->i_lun_guid, "lun-guid", 2795 KSTAT_DATA_STRING); 2796 kstat_named_init(&ks_lu->i_lun_alias, "lun-alias", 2797 KSTAT_DATA_STRING); 2798 2799 /* convert guid to hex string */ 2800 int i; 2801 uint8_t *p = ilu->ilu_lu->lu_id->ident; 2802 bzero(ilu->ilu_ascii_hex_guid, sizeof (ilu->ilu_ascii_hex_guid)); 2803 for (i = 0; i < STMF_GUID_INPUT / 2; i++) { 2804 (void) sprintf(&ilu->ilu_ascii_hex_guid[i * 2], "%02x", p[i]); 2805 } 2806 kstat_named_setstr(&ks_lu->i_lun_guid, 2807 (const char *)ilu->ilu_ascii_hex_guid); 2808 kstat_named_setstr(&ks_lu->i_lun_alias, 2809 (const char *)ilu->ilu_lu->lu_alias); 2810 kstat_install(ilu->ilu_kstat_info); 2811 2812 /* create kstat lun io */ 2813 bzero(ks_nm, sizeof (ks_nm)); 2814 (void) sprintf(ks_nm, "stmf_lu_io_%"PRIxPTR"", (uintptr_t)ilu); 2815 if ((ilu->ilu_kstat_io = kstat_create(STMF_MODULE_NAME, 0, 2816 ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) { 2817 cmn_err(CE_WARN, "STMF: kstat_create lu_io failed"); 2818 return; 2819 } 2820 mutex_init(&ilu->ilu_kstat_lock, NULL, MUTEX_DRIVER, 0); 2821 ilu->ilu_kstat_io->ks_lock = &ilu->ilu_kstat_lock; 2822 kstat_install(ilu->ilu_kstat_io); 2823 } 2824 2825 static void 2826 stmf_create_kstat_lport(stmf_i_local_port_t *ilport) 2827 { 2828 char ks_nm[KSTAT_STRLEN]; 2829 stmf_kstat_tgt_info_t *ks_tgt; 2830 int id, len; 2831 2832 /* create kstat lport info */ 2833 ks_tgt = (stmf_kstat_tgt_info_t *)kmem_zalloc(STMF_KSTAT_TGT_SZ, 2834 KM_NOSLEEP); 2835 if (ks_tgt == NULL) { 2836 cmn_err(CE_WARN, "STMF: kmem_zalloc failed"); 2837 return; 2838 } 2839 2840 bzero(ks_nm, sizeof (ks_nm)); 2841 (void) sprintf(ks_nm, "stmf_tgt_%"PRIxPTR"", (uintptr_t)ilport); 2842 if ((ilport->ilport_kstat_info = kstat_create(STMF_MODULE_NAME, 2843 0, ks_nm, "misc", KSTAT_TYPE_NAMED, 2844 sizeof (stmf_kstat_tgt_info_t) / sizeof (kstat_named_t), 2845 KSTAT_FLAG_VIRTUAL)) == NULL) { 2846 kmem_free(ks_tgt, STMF_KSTAT_TGT_SZ); 2847 cmn_err(CE_WARN, "STMF: kstat_create target failed"); 2848 return; 2849 } 2850 2851 ilport->ilport_kstat_info->ks_data_size = STMF_KSTAT_TGT_SZ; 2852 ilport->ilport_kstat_info->ks_data = ks_tgt; 2853 2854 kstat_named_init(&ks_tgt->i_tgt_name, "target-name", 2855 KSTAT_DATA_STRING); 2856 kstat_named_init(&ks_tgt->i_tgt_alias, "target-alias", 2857 KSTAT_DATA_STRING); 2858 kstat_named_init(&ks_tgt->i_protocol, "protocol", 2859 KSTAT_DATA_STRING); 2860 2861 /* ident might not be null terminated */ 2862 len = ilport->ilport_lport->lport_id->ident_length; 2863 bcopy(ilport->ilport_lport->lport_id->ident, 2864 ilport->ilport_kstat_tgt_name, len); 2865 ilport->ilport_kstat_tgt_name[len + 1] = NULL; 2866 kstat_named_setstr(&ks_tgt->i_tgt_name, 2867 (const char *)ilport->ilport_kstat_tgt_name); 2868 kstat_named_setstr(&ks_tgt->i_tgt_alias, 2869 (const char *)ilport->ilport_lport->lport_alias); 2870 /* protocol */ 2871 if ((id = ilport->ilport_lport->lport_id->protocol_id) > PROTOCOL_ANY) { 2872 cmn_err(CE_WARN, "STMF: protocol_id out of bound"); 2873 id = PROTOCOL_ANY; 2874 } 2875 kstat_named_setstr(&ks_tgt->i_protocol, protocol_ident[id]); 2876 kstat_install(ilport->ilport_kstat_info); 2877 2878 /* create kstat lport io */ 2879 bzero(ks_nm, sizeof (ks_nm)); 2880 (void) sprintf(ks_nm, "stmf_tgt_io_%"PRIxPTR"", (uintptr_t)ilport); 2881 if ((ilport->ilport_kstat_io = kstat_create(STMF_MODULE_NAME, 0, 2882 ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) { 2883 cmn_err(CE_WARN, "STMF: kstat_create target_io failed"); 2884 return; 2885 } 2886 mutex_init(&ilport->ilport_kstat_lock, NULL, MUTEX_DRIVER, 0); 2887 ilport->ilport_kstat_io->ks_lock = &ilport->ilport_kstat_lock; 2888 kstat_install(ilport->ilport_kstat_io); 2889 } 2890 2891 /* 2892 * set the asymmetric access state for a logical unit 2893 * caller is responsible for establishing SCSI unit attention on 2894 * state change 2895 */ 2896 stmf_status_t 2897 stmf_set_lu_access(stmf_lu_t *lu, uint8_t access_state) 2898 { 2899 stmf_i_lu_t *ilu; 2900 uint8_t *p1, *p2; 2901 2902 if ((access_state != STMF_LU_STANDBY) && 2903 (access_state != STMF_LU_ACTIVE)) { 2904 return (STMF_INVALID_ARG); 2905 } 2906 2907 p1 = &lu->lu_id->ident[0]; 2908 mutex_enter(&stmf_state.stmf_lock); 2909 if (stmf_state.stmf_inventory_locked) { 2910 mutex_exit(&stmf_state.stmf_lock); 2911 return (STMF_BUSY); 2912 } 2913 2914 for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) { 2915 p2 = &ilu->ilu_lu->lu_id->ident[0]; 2916 if (bcmp(p1, p2, 16) == 0) { 2917 break; 2918 } 2919 } 2920 2921 if (!ilu) { 2922 ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 2923 } else { 2924 /* 2925 * We're changing access state on an existing logical unit 2926 * Send the proxy registration message for this logical unit 2927 * if we're in alua mode. 2928 * If the requested state is STMF_LU_ACTIVE, we want to register 2929 * this logical unit. 2930 * If the requested state is STMF_LU_STANDBY, we're going to 2931 * abort all tasks for this logical unit. 2932 */ 2933 if (stmf_state.stmf_alua_state == 1 && 2934 access_state == STMF_LU_ACTIVE) { 2935 stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS; 2936 stmf_ic_msg_t *ic_reg_lun; 2937 if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 && 2938 lu->lu_lp->lp_alua_support) { 2939 ilu->ilu_alua = 1; 2940 /* allocate the register message */ 2941 ic_reg_lun = ic_lun_active_msg_alloc(p1, 2942 lu->lu_lp->lp_name, 2943 lu->lu_proxy_reg_arg_len, 2944 (uint8_t *)lu->lu_proxy_reg_arg, 2945 stmf_proxy_msg_id); 2946 /* send the message */ 2947 if (ic_reg_lun) { 2948 ic_ret = ic_tx_msg(ic_reg_lun); 2949 if (ic_ret == STMF_IC_MSG_SUCCESS) { 2950 stmf_proxy_msg_id++; 2951 } 2952 } 2953 } 2954 } else if (stmf_state.stmf_alua_state == 1 && 2955 access_state == STMF_LU_STANDBY) { 2956 /* abort all tasks for this lu */ 2957 stmf_task_lu_killall(lu, NULL, STMF_ABORTED); 2958 } 2959 } 2960 2961 ilu->ilu_access = access_state; 2962 2963 mutex_exit(&stmf_state.stmf_lock); 2964 return (STMF_SUCCESS); 2965 } 2966 2967 2968 stmf_status_t 2969 stmf_register_lu(stmf_lu_t *lu) 2970 { 2971 stmf_i_lu_t *ilu; 2972 uint8_t *p1, *p2; 2973 stmf_state_change_info_t ssci; 2974 stmf_id_data_t *luid; 2975 2976 if ((lu->lu_id->ident_type != ID_TYPE_NAA) || 2977 (lu->lu_id->ident_length != 16) || 2978 ((lu->lu_id->ident[0] & 0xf0) != 0x60)) { 2979 return (STMF_INVALID_ARG); 2980 } 2981 p1 = &lu->lu_id->ident[0]; 2982 mutex_enter(&stmf_state.stmf_lock); 2983 if (stmf_state.stmf_inventory_locked) { 2984 mutex_exit(&stmf_state.stmf_lock); 2985 return (STMF_BUSY); 2986 } 2987 2988 for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) { 2989 p2 = &ilu->ilu_lu->lu_id->ident[0]; 2990 if (bcmp(p1, p2, 16) == 0) { 2991 mutex_exit(&stmf_state.stmf_lock); 2992 return (STMF_ALREADY); 2993 } 2994 } 2995 2996 ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 2997 luid = stmf_lookup_id(&stmf_state.stmf_luid_list, 2998 lu->lu_id->ident_length, lu->lu_id->ident); 2999 if (luid) { 3000 luid->id_pt_to_object = (void *)ilu; 3001 ilu->ilu_luid = luid; 3002 } 3003 ilu->ilu_alias = NULL; 3004 3005 ilu->ilu_next = stmf_state.stmf_ilulist; 3006 ilu->ilu_prev = NULL; 3007 if (ilu->ilu_next) 3008 ilu->ilu_next->ilu_prev = ilu; 3009 stmf_state.stmf_ilulist = ilu; 3010 stmf_state.stmf_nlus++; 3011 if (lu->lu_lp) { 3012 ((stmf_i_lu_provider_t *) 3013 (lu->lu_lp->lp_stmf_private))->ilp_nlus++; 3014 } 3015 ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1; 3016 STMF_EVENT_ALLOC_HANDLE(ilu->ilu_event_hdl); 3017 stmf_create_kstat_lu(ilu); 3018 /* 3019 * register with proxy module if available and logical unit 3020 * is in active state 3021 */ 3022 if (stmf_state.stmf_alua_state == 1 && 3023 ilu->ilu_access == STMF_LU_ACTIVE) { 3024 stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS; 3025 stmf_ic_msg_t *ic_reg_lun; 3026 if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 && 3027 lu->lu_lp->lp_alua_support) { 3028 ilu->ilu_alua = 1; 3029 /* allocate the register message */ 3030 ic_reg_lun = ic_reg_lun_msg_alloc(p1, 3031 lu->lu_lp->lp_name, lu->lu_proxy_reg_arg_len, 3032 (uint8_t *)lu->lu_proxy_reg_arg, stmf_proxy_msg_id); 3033 /* send the message */ 3034 if (ic_reg_lun) { 3035 ic_ret = ic_tx_msg(ic_reg_lun); 3036 if (ic_ret == STMF_IC_MSG_SUCCESS) { 3037 stmf_proxy_msg_id++; 3038 } 3039 } 3040 } 3041 } 3042 mutex_exit(&stmf_state.stmf_lock); 3043 3044 /* XXX we should probably check if this lu can be brought online */ 3045 ilu->ilu_prev_state = STMF_STATE_ONLINE; 3046 if (stmf_state.stmf_service_running) { 3047 ssci.st_rflags = 0; 3048 ssci.st_additional_info = NULL; 3049 (void) stmf_ctl(STMF_CMD_LU_ONLINE, lu, &ssci); 3050 } 3051 3052 /* XXX: Generate event */ 3053 return (STMF_SUCCESS); 3054 } 3055 3056 stmf_status_t 3057 stmf_deregister_lu(stmf_lu_t *lu) 3058 { 3059 stmf_i_lu_t *ilu; 3060 3061 mutex_enter(&stmf_state.stmf_lock); 3062 if (stmf_state.stmf_inventory_locked) { 3063 mutex_exit(&stmf_state.stmf_lock); 3064 return (STMF_BUSY); 3065 } 3066 ilu = stmf_lookup_lu(lu); 3067 if (ilu == NULL) { 3068 mutex_exit(&stmf_state.stmf_lock); 3069 return (STMF_INVALID_ARG); 3070 } 3071 if (ilu->ilu_state == STMF_STATE_OFFLINE) { 3072 ASSERT(ilu->ilu_ntasks == ilu->ilu_ntasks_free); 3073 while (ilu->ilu_flags & ILU_STALL_DEREGISTER) { 3074 cv_wait(&stmf_state.stmf_cv, &stmf_state.stmf_lock); 3075 } 3076 if (ilu->ilu_ntasks) { 3077 stmf_i_scsi_task_t *itask, *nitask; 3078 3079 nitask = ilu->ilu_tasks; 3080 do { 3081 itask = nitask; 3082 nitask = itask->itask_lu_next; 3083 lu->lu_task_free(itask->itask_task); 3084 stmf_free(itask->itask_task); 3085 } while (nitask != NULL); 3086 3087 ilu->ilu_tasks = ilu->ilu_free_tasks = NULL; 3088 ilu->ilu_ntasks = ilu->ilu_ntasks_free = 0; 3089 } 3090 /* de-register with proxy if available */ 3091 if (ilu->ilu_access == STMF_LU_ACTIVE && 3092 stmf_state.stmf_alua_state == 1) { 3093 /* de-register with proxy module */ 3094 stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS; 3095 stmf_ic_msg_t *ic_dereg_lun; 3096 if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 && 3097 lu->lu_lp->lp_alua_support) { 3098 ilu->ilu_alua = 1; 3099 /* allocate the de-register message */ 3100 ic_dereg_lun = ic_dereg_lun_msg_alloc( 3101 lu->lu_id->ident, lu->lu_lp->lp_name, 0, 3102 NULL, stmf_proxy_msg_id); 3103 /* send the message */ 3104 if (ic_dereg_lun) { 3105 ic_ret = ic_tx_msg(ic_dereg_lun); 3106 if (ic_ret == STMF_IC_MSG_SUCCESS) { 3107 stmf_proxy_msg_id++; 3108 } 3109 } 3110 } 3111 } 3112 3113 if (ilu->ilu_next) 3114 ilu->ilu_next->ilu_prev = ilu->ilu_prev; 3115 if (ilu->ilu_prev) 3116 ilu->ilu_prev->ilu_next = ilu->ilu_next; 3117 else 3118 stmf_state.stmf_ilulist = ilu->ilu_next; 3119 stmf_state.stmf_nlus--; 3120 3121 if (ilu == stmf_state.stmf_svc_ilu_draining) { 3122 stmf_state.stmf_svc_ilu_draining = ilu->ilu_next; 3123 } 3124 if (ilu == stmf_state.stmf_svc_ilu_timing) { 3125 stmf_state.stmf_svc_ilu_timing = ilu->ilu_next; 3126 } 3127 if (lu->lu_lp) { 3128 ((stmf_i_lu_provider_t *) 3129 (lu->lu_lp->lp_stmf_private))->ilp_nlus--; 3130 } 3131 if (ilu->ilu_luid) { 3132 ((stmf_id_data_t *)ilu->ilu_luid)->id_pt_to_object = 3133 NULL; 3134 ilu->ilu_luid = NULL; 3135 } 3136 STMF_EVENT_FREE_HANDLE(ilu->ilu_event_hdl); 3137 } else { 3138 mutex_exit(&stmf_state.stmf_lock); 3139 return (STMF_BUSY); 3140 } 3141 if (ilu->ilu_kstat_info) { 3142 kmem_free(ilu->ilu_kstat_info->ks_data, 3143 ilu->ilu_kstat_info->ks_data_size); 3144 kstat_delete(ilu->ilu_kstat_info); 3145 } 3146 if (ilu->ilu_kstat_io) { 3147 kstat_delete(ilu->ilu_kstat_io); 3148 mutex_destroy(&ilu->ilu_kstat_lock); 3149 } 3150 stmf_delete_itl_kstat_by_guid(ilu->ilu_ascii_hex_guid); 3151 mutex_exit(&stmf_state.stmf_lock); 3152 return (STMF_SUCCESS); 3153 } 3154 3155 void 3156 stmf_set_port_standby(stmf_local_port_t *lport, uint16_t rtpid) 3157 { 3158 stmf_i_local_port_t *ilport = 3159 (stmf_i_local_port_t *)lport->lport_stmf_private; 3160 ilport->ilport_rtpid = rtpid; 3161 ilport->ilport_standby = 1; 3162 } 3163 3164 void 3165 stmf_set_port_alua(stmf_local_port_t *lport) 3166 { 3167 stmf_i_local_port_t *ilport = 3168 (stmf_i_local_port_t *)lport->lport_stmf_private; 3169 ilport->ilport_alua = 1; 3170 } 3171 3172 stmf_status_t 3173 stmf_register_local_port(stmf_local_port_t *lport) 3174 { 3175 stmf_i_local_port_t *ilport; 3176 stmf_state_change_info_t ssci; 3177 int start_workers = 0; 3178 3179 mutex_enter(&stmf_state.stmf_lock); 3180 if (stmf_state.stmf_inventory_locked) { 3181 mutex_exit(&stmf_state.stmf_lock); 3182 return (STMF_BUSY); 3183 } 3184 ilport = (stmf_i_local_port_t *)lport->lport_stmf_private; 3185 rw_init(&ilport->ilport_lock, NULL, RW_DRIVER, NULL); 3186 3187 ilport->ilport_instance = 3188 id_alloc_nosleep(stmf_state.stmf_ilport_inst_space); 3189 if (ilport->ilport_instance == -1) { 3190 mutex_exit(&stmf_state.stmf_lock); 3191 return (STMF_FAILURE); 3192 } 3193 ilport->ilport_next = stmf_state.stmf_ilportlist; 3194 ilport->ilport_prev = NULL; 3195 if (ilport->ilport_next) 3196 ilport->ilport_next->ilport_prev = ilport; 3197 stmf_state.stmf_ilportlist = ilport; 3198 stmf_state.stmf_nlports++; 3199 if (lport->lport_pp) { 3200 ((stmf_i_port_provider_t *) 3201 (lport->lport_pp->pp_stmf_private))->ipp_npps++; 3202 } 3203 ilport->ilport_tg = 3204 stmf_lookup_group_for_target(lport->lport_id->ident, 3205 lport->lport_id->ident_length); 3206 3207 /* 3208 * rtpid will/must be set if this is a standby port 3209 * only register ports that are not standby (proxy) ports 3210 * and ports that are alua participants (ilport_alua == 1) 3211 */ 3212 if (ilport->ilport_standby == 0) { 3213 ilport->ilport_rtpid = atomic_add_16_nv(&stmf_rtpid_counter, 1); 3214 } 3215 3216 if (stmf_state.stmf_alua_state == 1 && 3217 ilport->ilport_standby == 0 && 3218 ilport->ilport_alua == 1) { 3219 stmf_ic_msg_t *ic_reg_port; 3220 stmf_ic_msg_status_t ic_ret; 3221 stmf_local_port_t *lport; 3222 lport = ilport->ilport_lport; 3223 ic_reg_port = ic_reg_port_msg_alloc( 3224 lport->lport_id, ilport->ilport_rtpid, 3225 0, NULL, stmf_proxy_msg_id); 3226 if (ic_reg_port) { 3227 ic_ret = ic_tx_msg(ic_reg_port); 3228 if (ic_ret == STMF_IC_MSG_SUCCESS) { 3229 ilport->ilport_reg_msgid = stmf_proxy_msg_id++; 3230 } else { 3231 cmn_err(CE_WARN, "error on port registration " 3232 "port - %s", ilport->ilport_kstat_tgt_name); 3233 } 3234 } 3235 } 3236 STMF_EVENT_ALLOC_HANDLE(ilport->ilport_event_hdl); 3237 stmf_create_kstat_lport(ilport); 3238 if (stmf_workers_state == STMF_WORKERS_DISABLED) { 3239 stmf_workers_state = STMF_WORKERS_ENABLING; 3240 start_workers = 1; 3241 } 3242 mutex_exit(&stmf_state.stmf_lock); 3243 3244 if (start_workers) 3245 stmf_worker_init(); 3246 3247 /* XXX we should probably check if this lport can be brought online */ 3248 ilport->ilport_prev_state = STMF_STATE_ONLINE; 3249 if (stmf_state.stmf_service_running) { 3250 ssci.st_rflags = 0; 3251 ssci.st_additional_info = NULL; 3252 (void) stmf_ctl(STMF_CMD_LPORT_ONLINE, lport, &ssci); 3253 } 3254 3255 /* XXX: Generate event */ 3256 return (STMF_SUCCESS); 3257 } 3258 3259 stmf_status_t 3260 stmf_deregister_local_port(stmf_local_port_t *lport) 3261 { 3262 stmf_i_local_port_t *ilport; 3263 3264 mutex_enter(&stmf_state.stmf_lock); 3265 if (stmf_state.stmf_inventory_locked) { 3266 mutex_exit(&stmf_state.stmf_lock); 3267 return (STMF_BUSY); 3268 } 3269 3270 ilport = (stmf_i_local_port_t *)lport->lport_stmf_private; 3271 3272 /* 3273 * deregister ports that are not standby (proxy) 3274 */ 3275 if (stmf_state.stmf_alua_state == 1 && 3276 ilport->ilport_standby == 0 && 3277 ilport->ilport_alua == 1) { 3278 stmf_ic_msg_t *ic_dereg_port; 3279 stmf_ic_msg_status_t ic_ret; 3280 ic_dereg_port = ic_dereg_port_msg_alloc( 3281 lport->lport_id, 0, NULL, stmf_proxy_msg_id); 3282 if (ic_dereg_port) { 3283 ic_ret = ic_tx_msg(ic_dereg_port); 3284 if (ic_ret == STMF_IC_MSG_SUCCESS) { 3285 stmf_proxy_msg_id++; 3286 } 3287 } 3288 } 3289 3290 if (ilport->ilport_nsessions == 0) { 3291 if (ilport->ilport_next) 3292 ilport->ilport_next->ilport_prev = ilport->ilport_prev; 3293 if (ilport->ilport_prev) 3294 ilport->ilport_prev->ilport_next = ilport->ilport_next; 3295 else 3296 stmf_state.stmf_ilportlist = ilport->ilport_next; 3297 id_free(stmf_state.stmf_ilport_inst_space, 3298 ilport->ilport_instance); 3299 rw_destroy(&ilport->ilport_lock); 3300 stmf_state.stmf_nlports--; 3301 if (lport->lport_pp) { 3302 ((stmf_i_port_provider_t *) 3303 (lport->lport_pp->pp_stmf_private))->ipp_npps--; 3304 } 3305 ilport->ilport_tg = NULL; 3306 STMF_EVENT_FREE_HANDLE(ilport->ilport_event_hdl); 3307 } else { 3308 mutex_exit(&stmf_state.stmf_lock); 3309 return (STMF_BUSY); 3310 } 3311 if (ilport->ilport_kstat_info) { 3312 kmem_free(ilport->ilport_kstat_info->ks_data, 3313 ilport->ilport_kstat_info->ks_data_size); 3314 kstat_delete(ilport->ilport_kstat_info); 3315 } 3316 if (ilport->ilport_kstat_io) { 3317 kstat_delete(ilport->ilport_kstat_io); 3318 mutex_destroy(&ilport->ilport_kstat_lock); 3319 } 3320 stmf_delete_itl_kstat_by_lport(ilport->ilport_kstat_tgt_name); 3321 mutex_exit(&stmf_state.stmf_lock); 3322 return (STMF_SUCCESS); 3323 } 3324 3325 /* 3326 * Rport id/instance mappings remain valid until STMF is unloaded 3327 */ 3328 static int 3329 stmf_irport_compare(const void *void_irport1, const void *void_irport2) 3330 { 3331 const stmf_i_remote_port_t *irport1 = void_irport1; 3332 const stmf_i_remote_port_t *irport2 = void_irport2; 3333 int result; 3334 3335 /* Sort by code set then ident */ 3336 if (irport1->irport_id->code_set < 3337 irport2->irport_id->code_set) { 3338 return (-1); 3339 } else if (irport1->irport_id->code_set > 3340 irport2->irport_id->code_set) { 3341 return (1); 3342 } 3343 3344 /* Next by ident length */ 3345 if (irport1->irport_id->ident_length < 3346 irport2->irport_id->ident_length) { 3347 return (-1); 3348 } else if (irport1->irport_id->ident_length > 3349 irport2->irport_id->ident_length) { 3350 return (1); 3351 } 3352 3353 /* Code set and ident length both match, now compare idents */ 3354 result = memcmp(irport1->irport_id->ident, 3355 irport2->irport_id->ident, 3356 irport1->irport_id->ident_length); 3357 3358 if (result < 0) { 3359 return (-1); 3360 } else if (result > 0) { 3361 return (1); 3362 } 3363 3364 return (0); 3365 } 3366 3367 static stmf_i_remote_port_t * 3368 stmf_irport_create(scsi_devid_desc_t *rport_devid) 3369 { 3370 int alloc_len; 3371 stmf_i_remote_port_t *irport; 3372 3373 /* 3374 * Lookup will bump the refcnt if there's an existing rport 3375 * context for this identifier. 3376 */ 3377 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 3378 3379 alloc_len = sizeof (*irport) + sizeof (scsi_devid_desc_t) + 3380 rport_devid->ident_length - 1; 3381 irport = kmem_zalloc(alloc_len, KM_NOSLEEP); 3382 if (irport == NULL) { 3383 return (NULL); 3384 } 3385 3386 irport->irport_instance = 3387 id_alloc_nosleep(stmf_state.stmf_irport_inst_space); 3388 if (irport->irport_instance == -1) { 3389 kmem_free(irport, alloc_len); 3390 return (NULL); 3391 } 3392 3393 irport->irport_id = 3394 (struct scsi_devid_desc *)(irport + 1); /* Ptr. Arith. */ 3395 bcopy(rport_devid, irport->irport_id, 3396 sizeof (scsi_devid_desc_t) + rport_devid->ident_length - 1); 3397 irport->irport_refcnt = 1; 3398 mutex_init(&irport->irport_mutex, NULL, MUTEX_DEFAULT, NULL); 3399 3400 return (irport); 3401 } 3402 3403 static void 3404 stmf_irport_destroy(stmf_i_remote_port_t *irport) 3405 { 3406 id_free(stmf_state.stmf_irport_inst_space, irport->irport_instance); 3407 mutex_destroy(&irport->irport_mutex); 3408 kmem_free(irport, sizeof (*irport) + sizeof (scsi_devid_desc_t) + 3409 irport->irport_id->ident_length - 1); 3410 } 3411 3412 static stmf_i_remote_port_t * 3413 stmf_irport_register(scsi_devid_desc_t *rport_devid) 3414 { 3415 stmf_i_remote_port_t *irport; 3416 3417 mutex_enter(&stmf_state.stmf_lock); 3418 3419 /* 3420 * Lookup will bump the refcnt if there's an existing rport 3421 * context for this identifier. 3422 */ 3423 if ((irport = stmf_irport_lookup_locked(rport_devid)) != NULL) { 3424 mutex_exit(&stmf_state.stmf_lock); 3425 return (irport); 3426 } 3427 3428 irport = stmf_irport_create(rport_devid); 3429 if (irport == NULL) { 3430 mutex_exit(&stmf_state.stmf_lock); 3431 return (NULL); 3432 } 3433 3434 avl_add(&stmf_state.stmf_irportlist, irport); 3435 mutex_exit(&stmf_state.stmf_lock); 3436 3437 return (irport); 3438 } 3439 3440 static stmf_i_remote_port_t * 3441 stmf_irport_lookup_locked(scsi_devid_desc_t *rport_devid) 3442 { 3443 stmf_i_remote_port_t *irport; 3444 stmf_i_remote_port_t tmp_irport; 3445 3446 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 3447 tmp_irport.irport_id = rport_devid; 3448 irport = avl_find(&stmf_state.stmf_irportlist, &tmp_irport, NULL); 3449 if (irport != NULL) { 3450 mutex_enter(&irport->irport_mutex); 3451 irport->irport_refcnt++; 3452 mutex_exit(&irport->irport_mutex); 3453 } 3454 3455 return (irport); 3456 } 3457 3458 static void 3459 stmf_irport_deregister(stmf_i_remote_port_t *irport) 3460 { 3461 /* 3462 * If we were actually going to remove unreferenced remote ports 3463 * we would want to acquire stmf_state.stmf_lock before getting 3464 * the irport mutex. 3465 * 3466 * Instead we're just going to leave it there even if unreferenced. 3467 */ 3468 mutex_enter(&irport->irport_mutex); 3469 irport->irport_refcnt--; 3470 mutex_exit(&irport->irport_mutex); 3471 } 3472 3473 /* 3474 * Port provider has to make sure that register/deregister session and 3475 * port are serialized calls. 3476 */ 3477 stmf_status_t 3478 stmf_register_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss) 3479 { 3480 stmf_i_scsi_session_t *iss; 3481 stmf_i_local_port_t *ilport = (stmf_i_local_port_t *) 3482 lport->lport_stmf_private; 3483 uint8_t lun[8]; 3484 3485 /* 3486 * Port state has to be online to register a scsi session. It is 3487 * possible that we started an offline operation and a new SCSI 3488 * session started at the same time (in that case also we are going 3489 * to fail the registeration). But any other state is simply 3490 * a bad port provider implementation. 3491 */ 3492 if (ilport->ilport_state != STMF_STATE_ONLINE) { 3493 if (ilport->ilport_state != STMF_STATE_OFFLINING) { 3494 stmf_trace(lport->lport_alias, "Port is trying to " 3495 "register a session while the state is neither " 3496 "online nor offlining"); 3497 } 3498 return (STMF_FAILURE); 3499 } 3500 bzero(lun, 8); 3501 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private; 3502 if ((iss->iss_irport = stmf_irport_register(ss->ss_rport_id)) == NULL) { 3503 stmf_trace(lport->lport_alias, "Could not register " 3504 "remote port during session registration"); 3505 return (STMF_FAILURE); 3506 } 3507 3508 iss->iss_flags |= ISS_BEING_CREATED; 3509 3510 /* sessions use the ilport_lock. No separate lock is required */ 3511 iss->iss_lockp = &ilport->ilport_lock; 3512 3513 if (iss->iss_sm != NULL) 3514 cmn_err(CE_PANIC, "create lun map called with non NULL map"); 3515 iss->iss_sm = (stmf_lun_map_t *)kmem_zalloc(sizeof (stmf_lun_map_t), 3516 KM_SLEEP); 3517 3518 mutex_enter(&stmf_state.stmf_lock); 3519 rw_enter(&ilport->ilport_lock, RW_WRITER); 3520 (void) stmf_session_create_lun_map(ilport, iss); 3521 ilport->ilport_nsessions++; 3522 iss->iss_next = ilport->ilport_ss_list; 3523 ilport->ilport_ss_list = iss; 3524 rw_exit(&ilport->ilport_lock); 3525 mutex_exit(&stmf_state.stmf_lock); 3526 3527 iss->iss_creation_time = ddi_get_time(); 3528 ss->ss_session_id = atomic_add_64_nv(&stmf_session_counter, 1); 3529 iss->iss_flags &= ~ISS_BEING_CREATED; 3530 /* XXX should we remove ISS_LUN_INVENTORY_CHANGED on new session? */ 3531 iss->iss_flags &= ~ISS_LUN_INVENTORY_CHANGED; 3532 DTRACE_PROBE2(session__online, stmf_local_port_t *, lport, 3533 stmf_scsi_session_t *, ss); 3534 return (STMF_SUCCESS); 3535 } 3536 3537 void 3538 stmf_deregister_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss) 3539 { 3540 stmf_i_local_port_t *ilport = (stmf_i_local_port_t *) 3541 lport->lport_stmf_private; 3542 stmf_i_scsi_session_t *iss, **ppss; 3543 int found = 0; 3544 stmf_ic_msg_t *ic_session_dereg; 3545 stmf_status_t ic_ret = STMF_FAILURE; 3546 3547 DTRACE_PROBE2(session__offline, stmf_local_port_t *, lport, 3548 stmf_scsi_session_t *, ss); 3549 3550 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private; 3551 if (ss->ss_rport_alias) { 3552 ss->ss_rport_alias = NULL; 3553 } 3554 3555 try_dereg_ss_again: 3556 mutex_enter(&stmf_state.stmf_lock); 3557 atomic_and_32(&iss->iss_flags, 3558 ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS)); 3559 if (iss->iss_flags & ISS_EVENT_ACTIVE) { 3560 mutex_exit(&stmf_state.stmf_lock); 3561 delay(1); 3562 goto try_dereg_ss_again; 3563 } 3564 3565 /* dereg proxy session if not standby port */ 3566 if (stmf_state.stmf_alua_state == 1 && 3567 ilport->ilport_standby == 0 && 3568 ilport->ilport_alua == 1) { 3569 ic_session_dereg = ic_session_dereg_msg_alloc( 3570 ss, stmf_proxy_msg_id); 3571 if (ic_session_dereg) { 3572 ic_ret = ic_tx_msg(ic_session_dereg); 3573 if (ic_ret == STMF_IC_MSG_SUCCESS) { 3574 stmf_proxy_msg_id++; 3575 } 3576 } 3577 } 3578 3579 rw_enter(&ilport->ilport_lock, RW_WRITER); 3580 for (ppss = &ilport->ilport_ss_list; *ppss != NULL; 3581 ppss = &((*ppss)->iss_next)) { 3582 if (iss == (*ppss)) { 3583 *ppss = (*ppss)->iss_next; 3584 found = 1; 3585 break; 3586 } 3587 } 3588 if (!found) { 3589 cmn_err(CE_PANIC, "Deregister session called for non existent" 3590 " session"); 3591 } 3592 ilport->ilport_nsessions--; 3593 3594 stmf_irport_deregister(iss->iss_irport); 3595 (void) stmf_session_destroy_lun_map(ilport, iss); 3596 rw_exit(&ilport->ilport_lock); 3597 mutex_exit(&stmf_state.stmf_lock); 3598 } 3599 3600 stmf_i_scsi_session_t * 3601 stmf_session_id_to_issptr(uint64_t session_id, int stay_locked) 3602 { 3603 stmf_i_local_port_t *ilport; 3604 stmf_i_scsi_session_t *iss; 3605 3606 mutex_enter(&stmf_state.stmf_lock); 3607 for (ilport = stmf_state.stmf_ilportlist; ilport != NULL; 3608 ilport = ilport->ilport_next) { 3609 rw_enter(&ilport->ilport_lock, RW_WRITER); 3610 for (iss = ilport->ilport_ss_list; iss != NULL; 3611 iss = iss->iss_next) { 3612 if (iss->iss_ss->ss_session_id == session_id) { 3613 if (!stay_locked) 3614 rw_exit(&ilport->ilport_lock); 3615 mutex_exit(&stmf_state.stmf_lock); 3616 return (iss); 3617 } 3618 } 3619 rw_exit(&ilport->ilport_lock); 3620 } 3621 mutex_exit(&stmf_state.stmf_lock); 3622 return (NULL); 3623 } 3624 3625 #define MAX_ALIAS 128 3626 3627 static int 3628 stmf_itl_kstat_compare(const void *itl_kstat_1, const void *itl_kstat_2) 3629 { 3630 const stmf_i_itl_kstat_t *kstat_nm1 = itl_kstat_1; 3631 const stmf_i_itl_kstat_t *kstat_nm2 = itl_kstat_2; 3632 int ret; 3633 3634 ret = strcmp(kstat_nm1->iitl_kstat_nm, kstat_nm2->iitl_kstat_nm); 3635 if (ret < 0) { 3636 return (-1); 3637 } else if (ret > 0) { 3638 return (1); 3639 } 3640 return (0); 3641 } 3642 3643 static stmf_i_itl_kstat_t * 3644 stmf_itl_kstat_lookup(char *kstat_nm) 3645 { 3646 stmf_i_itl_kstat_t tmp; 3647 stmf_i_itl_kstat_t *itl_kstat; 3648 3649 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 3650 (void) strcpy(tmp.iitl_kstat_nm, kstat_nm); 3651 itl_kstat = avl_find(&stmf_state.stmf_itl_kstat_list, &tmp, NULL); 3652 return (itl_kstat); 3653 } 3654 3655 static void 3656 stmf_delete_itl_kstat_by_lport(char *tgt) 3657 { 3658 stmf_i_itl_kstat_t *ks_itl, *next; 3659 3660 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 3661 ks_itl = avl_first(&stmf_state.stmf_itl_kstat_list); 3662 for (; ks_itl != NULL; ks_itl = next) { 3663 next = AVL_NEXT(&stmf_state.stmf_itl_kstat_list, ks_itl); 3664 if (strcmp(ks_itl->iitl_kstat_lport, tgt) == 0) { 3665 stmf_teardown_itl_kstats(ks_itl); 3666 avl_remove(&stmf_state.stmf_itl_kstat_list, ks_itl); 3667 kmem_free(ks_itl, sizeof (stmf_i_itl_kstat_t)); 3668 } 3669 } 3670 } 3671 3672 static void 3673 stmf_delete_itl_kstat_by_guid(char *guid) 3674 { 3675 stmf_i_itl_kstat_t *ks_itl, *next; 3676 3677 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 3678 ks_itl = avl_first(&stmf_state.stmf_itl_kstat_list); 3679 for (; ks_itl != NULL; ks_itl = next) { 3680 next = AVL_NEXT(&stmf_state.stmf_itl_kstat_list, ks_itl); 3681 if (strcmp(ks_itl->iitl_kstat_guid, guid) == 0) { 3682 stmf_teardown_itl_kstats(ks_itl); 3683 avl_remove(&stmf_state.stmf_itl_kstat_list, ks_itl); 3684 kmem_free(ks_itl, sizeof (stmf_i_itl_kstat_t)); 3685 } 3686 } 3687 } 3688 3689 static stmf_i_itl_kstat_t * 3690 stmf_itl_kstat_create(stmf_itl_data_t *itl, char *nm, 3691 scsi_devid_desc_t *lport, scsi_devid_desc_t *lun) 3692 { 3693 stmf_i_itl_kstat_t *ks_itl; 3694 int i, len; 3695 3696 ASSERT(mutex_owned(&stmf_state.stmf_lock)); 3697 if ((ks_itl = stmf_itl_kstat_lookup(nm)) != NULL) 3698 return (ks_itl); 3699 3700 len = sizeof (stmf_i_itl_kstat_t); 3701 ks_itl = kmem_zalloc(len, KM_NOSLEEP); 3702 if (ks_itl == NULL) 3703 return (NULL); 3704 3705 (void) strcpy(ks_itl->iitl_kstat_nm, nm); 3706 bcopy(lport->ident, ks_itl->iitl_kstat_lport, lport->ident_length); 3707 ks_itl->iitl_kstat_lport[lport->ident_length] = '\0'; 3708 for (i = 0; i < STMF_GUID_INPUT / 2; i++) { 3709 (void) sprintf(&ks_itl->iitl_kstat_guid[i * 2], "%02x", 3710 lun->ident[i]); 3711 } 3712 ks_itl->iitl_kstat_strbuf = itl->itl_kstat_strbuf; 3713 ks_itl->iitl_kstat_strbuflen = itl->itl_kstat_strbuflen; 3714 ks_itl->iitl_kstat_info = itl->itl_kstat_info; 3715 ks_itl->iitl_kstat_taskq = itl->itl_kstat_taskq; 3716 ks_itl->iitl_kstat_lu_xfer = itl->itl_kstat_lu_xfer; 3717 ks_itl->iitl_kstat_lport_xfer = itl->itl_kstat_lport_xfer; 3718 avl_add(&stmf_state.stmf_itl_kstat_list, ks_itl); 3719 3720 return (ks_itl); 3721 } 3722 3723 stmf_status_t 3724 stmf_setup_itl_kstats(stmf_itl_data_t *itl) 3725 { 3726 char ks_itl_id[32]; 3727 char ks_nm[KSTAT_STRLEN]; 3728 char ks_itl_nm[KSTAT_STRLEN]; 3729 stmf_kstat_itl_info_t *ks_itl; 3730 stmf_scsi_session_t *ss; 3731 stmf_i_scsi_session_t *iss; 3732 stmf_i_local_port_t *ilport; 3733 char *strbuf; 3734 int id, len, i; 3735 char *rport_alias; 3736 char *lport_alias; 3737 char *lu_alias; 3738 stmf_i_itl_kstat_t *tmp_kstat; 3739 3740 /* 3741 * Allocate enough memory in the ITL to hold the relevant 3742 * identifiers. 3743 * rport and lport identifiers come from the stmf_scsi_session_t. 3744 * ident might not be null terminated. 3745 */ 3746 ss = itl->itl_session->iss_ss; 3747 iss = ss->ss_stmf_private; 3748 ilport = ss->ss_lport->lport_stmf_private; 3749 (void) snprintf(ks_itl_id, 32, "%d.%d.%d", 3750 iss->iss_irport->irport_instance, ilport->ilport_instance, 3751 itl->itl_lun); 3752 3753 (void) snprintf(ks_itl_nm, KSTAT_STRLEN, "itl_%s", ks_itl_id); 3754 /* 3755 * let's verify this itl_kstat already exist 3756 */ 3757 if ((tmp_kstat = stmf_itl_kstat_lookup(ks_itl_nm)) != NULL) { 3758 itl->itl_kstat_strbuf = tmp_kstat->iitl_kstat_strbuf; 3759 itl->itl_kstat_strbuflen = tmp_kstat->iitl_kstat_strbuflen; 3760 itl->itl_kstat_info = tmp_kstat->iitl_kstat_info; 3761 itl->itl_kstat_taskq = tmp_kstat->iitl_kstat_taskq; 3762 itl->itl_kstat_lu_xfer = tmp_kstat->iitl_kstat_lu_xfer; 3763 itl->itl_kstat_lport_xfer = tmp_kstat->iitl_kstat_lport_xfer; 3764 return (STMF_SUCCESS); 3765 } 3766 3767 /* New itl_kstat */ 3768 rport_alias = (ss->ss_rport_alias == NULL) ? 3769 "" : ss->ss_rport_alias; 3770 lport_alias = (ss->ss_lport->lport_alias == NULL) ? 3771 "" : ss->ss_lport->lport_alias; 3772 lu_alias = (itl->itl_ilu->ilu_lu->lu_alias == NULL) ? 3773 "" : itl->itl_ilu->ilu_lu->lu_alias; 3774 3775 itl->itl_kstat_strbuflen = (ss->ss_rport_id->ident_length + 1) + 3776 (strnlen(rport_alias, MAX_ALIAS) + 1) + 3777 (ss->ss_lport->lport_id->ident_length + 1) + 3778 (strnlen(lport_alias, MAX_ALIAS) + 1) + 3779 (STMF_GUID_INPUT + 1) + 3780 (strnlen(lu_alias, MAX_ALIAS) + 1) + 3781 MAX_PROTO_STR_LEN; 3782 itl->itl_kstat_strbuf = kmem_zalloc(itl->itl_kstat_strbuflen, 3783 KM_NOSLEEP); 3784 if (itl->itl_kstat_strbuf == NULL) { 3785 return (STMF_ALLOC_FAILURE); 3786 } 3787 3788 ks_itl = (stmf_kstat_itl_info_t *)kmem_zalloc(sizeof (*ks_itl), 3789 KM_NOSLEEP); 3790 if (ks_itl == NULL) { 3791 kmem_free(itl->itl_kstat_strbuf, itl->itl_kstat_strbuflen); 3792 return (STMF_ALLOC_FAILURE); 3793 } 3794 3795 if ((itl->itl_kstat_info = kstat_create(STMF_MODULE_NAME, 3796 0, ks_itl_nm, "misc", KSTAT_TYPE_NAMED, 3797 sizeof (stmf_kstat_itl_info_t) / sizeof (kstat_named_t), 3798 KSTAT_FLAG_VIRTUAL)) == NULL) { 3799 goto itl_kstat_cleanup; 3800 } 3801 3802 itl->itl_kstat_info->ks_data_size += itl->itl_kstat_strbuflen; 3803 itl->itl_kstat_info->ks_data = ks_itl; 3804 3805 kstat_named_init(&ks_itl->i_rport_name, "rport-name", 3806 KSTAT_DATA_STRING); 3807 kstat_named_init(&ks_itl->i_rport_alias, "rport-alias", 3808 KSTAT_DATA_STRING); 3809 kstat_named_init(&ks_itl->i_lport_name, "lport-name", 3810 KSTAT_DATA_STRING); 3811 kstat_named_init(&ks_itl->i_lport_alias, "lport-alias", 3812 KSTAT_DATA_STRING); 3813 kstat_named_init(&ks_itl->i_protocol, "protocol", 3814 KSTAT_DATA_STRING); 3815 kstat_named_init(&ks_itl->i_lu_guid, "lu-guid", 3816 KSTAT_DATA_STRING); 3817 kstat_named_init(&ks_itl->i_lu_alias, "lu-alias", 3818 KSTAT_DATA_STRING); 3819 kstat_named_init(&ks_itl->i_lu_number, "lu-number", 3820 KSTAT_DATA_UINT64); 3821 kstat_named_init(&ks_itl->i_task_waitq_elapsed, "task-waitq-elapsed", 3822 KSTAT_DATA_UINT64); 3823 kstat_named_init(&ks_itl->i_task_read_elapsed, "task-read-elapsed", 3824 KSTAT_DATA_UINT64); 3825 kstat_named_init(&ks_itl->i_task_write_elapsed, "task-write-elapsed", 3826 KSTAT_DATA_UINT64); 3827 kstat_named_init(&ks_itl->i_lu_read_elapsed, "lu-read-elapsed", 3828 KSTAT_DATA_UINT64); 3829 kstat_named_init(&ks_itl->i_lu_write_elapsed, "lu-write-elapsed", 3830 KSTAT_DATA_UINT64); 3831 kstat_named_init(&ks_itl->i_lport_read_elapsed, "lport-read-elapsed", 3832 KSTAT_DATA_UINT64); 3833 kstat_named_init(&ks_itl->i_lport_write_elapsed, "lport-write-elapsed", 3834 KSTAT_DATA_UINT64); 3835 3836 strbuf = itl->itl_kstat_strbuf; 3837 3838 /* Rport */ 3839 len = ss->ss_rport_id->ident_length; 3840 bcopy(ss->ss_rport_id->ident, strbuf, len); 3841 strbuf += len; 3842 *strbuf = '\0'; 3843 kstat_named_setstr(&ks_itl->i_rport_name, strbuf - len); 3844 strbuf++; 3845 3846 len = strnlen(rport_alias, MAX_ALIAS); 3847 (void) strncpy(strbuf, rport_alias, len + 1); 3848 kstat_named_setstr(&ks_itl->i_rport_alias, strbuf); 3849 strbuf += len + 1; 3850 3851 /* Lport */ 3852 len = ss->ss_lport->lport_id->ident_length; 3853 bcopy(ss->ss_lport->lport_id->ident, strbuf, len); 3854 strbuf += len; 3855 *strbuf = '\0'; 3856 kstat_named_setstr(&ks_itl->i_lport_name, strbuf - len); 3857 strbuf++; 3858 3859 len = strnlen(lport_alias, MAX_ALIAS); 3860 (void) strncpy(strbuf, lport_alias, len + 1); 3861 kstat_named_setstr(&ks_itl->i_lport_alias, strbuf); 3862 strbuf += len + 1; 3863 3864 id = (ss->ss_lport->lport_id->protocol_id > PROTOCOL_ANY) ? 3865 PROTOCOL_ANY : ss->ss_lport->lport_id->protocol_id; 3866 kstat_named_setstr(&ks_itl->i_protocol, protocol_ident[id]); 3867 3868 /* LU */ 3869 for (i = 0; i < STMF_GUID_INPUT / 2; i++) { 3870 (void) sprintf(&strbuf[i * 2], "%02x", 3871 itl->itl_ilu->ilu_lu->lu_id->ident[i]); 3872 } 3873 kstat_named_setstr(&ks_itl->i_lu_guid, strbuf); 3874 strbuf += STMF_GUID_INPUT + 1; 3875 3876 len = strnlen(lu_alias, MAX_ALIAS); 3877 (void) strncpy(strbuf, lu_alias, len + 1); 3878 kstat_named_setstr(&ks_itl->i_lu_alias, strbuf); 3879 strbuf += len + 1; 3880 3881 ks_itl->i_lu_number.value.ui64 = itl->itl_lun; 3882 3883 /* Now create the I/O kstats */ 3884 (void) snprintf(ks_nm, KSTAT_STRLEN, "itl_tasks_%s", ks_itl_id); 3885 if ((itl->itl_kstat_taskq = kstat_create(STMF_MODULE_NAME, 0, 3886 ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) { 3887 goto itl_kstat_cleanup; 3888 } 3889 3890 (void) snprintf(ks_nm, KSTAT_STRLEN, "itl_lu_%s", ks_itl_id); 3891 if ((itl->itl_kstat_lu_xfer = kstat_create(STMF_MODULE_NAME, 0, 3892 ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) { 3893 goto itl_kstat_cleanup; 3894 } 3895 3896 (void) snprintf(ks_nm, KSTAT_STRLEN, "itl_lport_%s", ks_itl_id); 3897 if ((itl->itl_kstat_lport_xfer = kstat_create(STMF_MODULE_NAME, 0, 3898 ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) { 3899 goto itl_kstat_cleanup; 3900 } 3901 3902 /* Install all the kstats */ 3903 kstat_install(itl->itl_kstat_info); 3904 kstat_install(itl->itl_kstat_taskq); 3905 kstat_install(itl->itl_kstat_lu_xfer); 3906 kstat_install(itl->itl_kstat_lport_xfer); 3907 3908 /* Add new itl_kstat to stmf_itl_kstat_list */ 3909 if (stmf_itl_kstat_create(itl, ks_itl_nm, ss->ss_lport->lport_id, 3910 itl->itl_ilu->ilu_lu->lu_id) != NULL) 3911 return (STMF_SUCCESS); 3912 3913 itl_kstat_cleanup: 3914 if (itl->itl_kstat_taskq) 3915 kstat_delete(itl->itl_kstat_taskq); 3916 if (itl->itl_kstat_lu_xfer) 3917 kstat_delete(itl->itl_kstat_lu_xfer); 3918 if (itl->itl_kstat_lport_xfer) 3919 kstat_delete(itl->itl_kstat_lport_xfer); 3920 if (itl->itl_kstat_info) 3921 kstat_delete(itl->itl_kstat_info); 3922 kmem_free(ks_itl, sizeof (*ks_itl)); 3923 kmem_free(itl->itl_kstat_strbuf, itl->itl_kstat_strbuflen); 3924 cmn_err(CE_WARN, "STMF: kstat_create itl failed"); 3925 return (STMF_ALLOC_FAILURE); 3926 } 3927 3928 static void 3929 stmf_teardown_itl_kstats(stmf_i_itl_kstat_t *ks) 3930 { 3931 kstat_delete(ks->iitl_kstat_lport_xfer); 3932 kstat_delete(ks->iitl_kstat_lu_xfer); 3933 kstat_delete(ks->iitl_kstat_taskq); 3934 kmem_free(ks->iitl_kstat_info->ks_data, sizeof (stmf_kstat_itl_info_t)); 3935 kstat_delete(ks->iitl_kstat_info); 3936 kmem_free(ks->iitl_kstat_strbuf, ks->iitl_kstat_strbuflen); 3937 } 3938 3939 void 3940 stmf_release_itl_handle(stmf_lu_t *lu, stmf_itl_data_t *itl) 3941 { 3942 stmf_itl_data_t **itlpp; 3943 stmf_i_lu_t *ilu; 3944 3945 ASSERT(itl->itl_flags & STMF_ITL_BEING_TERMINATED); 3946 3947 ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 3948 mutex_enter(&ilu->ilu_task_lock); 3949 for (itlpp = &ilu->ilu_itl_list; (*itlpp) != NULL; 3950 itlpp = &(*itlpp)->itl_next) { 3951 if ((*itlpp) == itl) 3952 break; 3953 } 3954 ASSERT((*itlpp) != NULL); 3955 *itlpp = itl->itl_next; 3956 mutex_exit(&ilu->ilu_task_lock); 3957 lu->lu_abort(lu, STMF_LU_ITL_HANDLE_REMOVED, itl->itl_handle, 3958 (uint32_t)itl->itl_hdlrm_reason); 3959 3960 kmem_free(itl, sizeof (*itl)); 3961 } 3962 3963 stmf_status_t 3964 stmf_register_itl_handle(stmf_lu_t *lu, uint8_t *lun, 3965 stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle) 3966 { 3967 stmf_itl_data_t *itl; 3968 stmf_i_scsi_session_t *iss; 3969 stmf_lun_map_ent_t *lun_map_ent; 3970 stmf_i_lu_t *ilu; 3971 uint16_t n; 3972 3973 ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 3974 if (ss == NULL) { 3975 iss = stmf_session_id_to_issptr(session_id, 1); 3976 if (iss == NULL) 3977 return (STMF_NOT_FOUND); 3978 } else { 3979 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private; 3980 } 3981 3982 /* 3983 * Acquire stmf_lock for stmf_itl_kstat_lookup. 3984 */ 3985 mutex_enter(&stmf_state.stmf_lock); 3986 rw_enter(iss->iss_lockp, RW_WRITER); 3987 n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8)); 3988 lun_map_ent = (stmf_lun_map_ent_t *) 3989 stmf_get_ent_from_map(iss->iss_sm, n); 3990 if ((lun_map_ent == NULL) || (lun_map_ent->ent_lu != lu)) { 3991 rw_exit(iss->iss_lockp); 3992 mutex_exit(&stmf_state.stmf_lock); 3993 return (STMF_NOT_FOUND); 3994 } 3995 if (lun_map_ent->ent_itl_datap != NULL) { 3996 rw_exit(iss->iss_lockp); 3997 mutex_exit(&stmf_state.stmf_lock); 3998 return (STMF_ALREADY); 3999 } 4000 4001 itl = (stmf_itl_data_t *)kmem_zalloc(sizeof (*itl), KM_NOSLEEP); 4002 if (itl == NULL) { 4003 rw_exit(iss->iss_lockp); 4004 mutex_exit(&stmf_state.stmf_lock); 4005 return (STMF_ALLOC_FAILURE); 4006 } 4007 4008 itl->itl_ilu = ilu; 4009 itl->itl_session = iss; 4010 itl->itl_counter = 1; 4011 itl->itl_lun = n; 4012 itl->itl_handle = itl_handle; 4013 4014 if (stmf_setup_itl_kstats(itl) != STMF_SUCCESS) { 4015 kmem_free(itl, sizeof (*itl)); 4016 rw_exit(iss->iss_lockp); 4017 mutex_exit(&stmf_state.stmf_lock); 4018 return (STMF_ALLOC_FAILURE); 4019 } 4020 4021 mutex_enter(&ilu->ilu_task_lock); 4022 itl->itl_next = ilu->ilu_itl_list; 4023 ilu->ilu_itl_list = itl; 4024 mutex_exit(&ilu->ilu_task_lock); 4025 lun_map_ent->ent_itl_datap = itl; 4026 rw_exit(iss->iss_lockp); 4027 mutex_exit(&stmf_state.stmf_lock); 4028 4029 return (STMF_SUCCESS); 4030 } 4031 4032 void 4033 stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl, uint8_t hdlrm_reason) 4034 { 4035 uint8_t old, new; 4036 4037 do { 4038 old = new = itl->itl_flags; 4039 if (old & STMF_ITL_BEING_TERMINATED) 4040 return; 4041 new |= STMF_ITL_BEING_TERMINATED; 4042 } while (atomic_cas_8(&itl->itl_flags, old, new) != old); 4043 itl->itl_hdlrm_reason = hdlrm_reason; 4044 4045 ASSERT(itl->itl_counter); 4046 4047 if (atomic_add_32_nv(&itl->itl_counter, -1)) 4048 return; 4049 4050 drv_usecwait(10); 4051 if (itl->itl_counter) 4052 return; 4053 4054 stmf_release_itl_handle(lu, itl); 4055 } 4056 4057 stmf_status_t 4058 stmf_deregister_all_lu_itl_handles(stmf_lu_t *lu) 4059 { 4060 stmf_i_lu_t *ilu; 4061 stmf_i_local_port_t *ilport; 4062 stmf_i_scsi_session_t *iss; 4063 stmf_lun_map_t *lm; 4064 stmf_lun_map_ent_t *ent; 4065 uint32_t nmaps, nu; 4066 stmf_itl_data_t **itl_list; 4067 int i; 4068 4069 ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 4070 4071 dereg_itl_start:; 4072 nmaps = ilu->ilu_ref_cnt; 4073 if (nmaps == 0) 4074 return (STMF_NOT_FOUND); 4075 itl_list = (stmf_itl_data_t **)kmem_zalloc( 4076 nmaps * sizeof (stmf_itl_data_t *), KM_SLEEP); 4077 mutex_enter(&stmf_state.stmf_lock); 4078 if (nmaps != ilu->ilu_ref_cnt) { 4079 /* Something changed, start all over */ 4080 mutex_exit(&stmf_state.stmf_lock); 4081 kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *)); 4082 goto dereg_itl_start; 4083 } 4084 nu = 0; 4085 for (ilport = stmf_state.stmf_ilportlist; ilport != NULL; 4086 ilport = ilport->ilport_next) { 4087 rw_enter(&ilport->ilport_lock, RW_WRITER); 4088 for (iss = ilport->ilport_ss_list; iss != NULL; 4089 iss = iss->iss_next) { 4090 lm = iss->iss_sm; 4091 if (!lm) 4092 continue; 4093 for (i = 0; i < lm->lm_nentries; i++) { 4094 if (lm->lm_plus[i] == NULL) 4095 continue; 4096 ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 4097 if ((ent->ent_lu == lu) && 4098 (ent->ent_itl_datap)) { 4099 itl_list[nu++] = ent->ent_itl_datap; 4100 ent->ent_itl_datap = NULL; 4101 if (nu == nmaps) { 4102 rw_exit(&ilport->ilport_lock); 4103 goto dai_scan_done; 4104 } 4105 } 4106 } /* lun table for a session */ 4107 } /* sessions */ 4108 rw_exit(&ilport->ilport_lock); 4109 } /* ports */ 4110 4111 dai_scan_done: 4112 mutex_exit(&stmf_state.stmf_lock); 4113 4114 for (i = 0; i < nu; i++) { 4115 stmf_do_itl_dereg(lu, itl_list[i], 4116 STMF_ITL_REASON_DEREG_REQUEST); 4117 } 4118 kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *)); 4119 4120 return (STMF_SUCCESS); 4121 } 4122 4123 stmf_status_t 4124 stmf_deregister_itl_handle(stmf_lu_t *lu, uint8_t *lun, 4125 stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle) 4126 { 4127 stmf_i_scsi_session_t *iss; 4128 stmf_itl_data_t *itl; 4129 stmf_lun_map_ent_t *ent; 4130 stmf_lun_map_t *lm; 4131 int i; 4132 uint16_t n; 4133 4134 if (ss == NULL) { 4135 if (session_id == STMF_SESSION_ID_NONE) 4136 return (STMF_INVALID_ARG); 4137 iss = stmf_session_id_to_issptr(session_id, 1); 4138 if (iss == NULL) 4139 return (STMF_NOT_FOUND); 4140 } else { 4141 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private; 4142 rw_enter(iss->iss_lockp, RW_WRITER); 4143 } 4144 lm = iss->iss_sm; 4145 if (lm == NULL) { 4146 rw_exit(iss->iss_lockp); 4147 return (STMF_NOT_FOUND); 4148 } 4149 4150 if (lun) { 4151 n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8)); 4152 ent = (stmf_lun_map_ent_t *) 4153 stmf_get_ent_from_map(iss->iss_sm, n); 4154 } else { 4155 if (itl_handle == NULL) { 4156 rw_exit(iss->iss_lockp); 4157 return (STMF_INVALID_ARG); 4158 } 4159 ent = NULL; 4160 for (i = 0; i < lm->lm_nentries; i++) { 4161 if (lm->lm_plus[i] == NULL) 4162 continue; 4163 ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 4164 if (ent->ent_itl_datap && 4165 (ent->ent_itl_datap->itl_handle == itl_handle)) { 4166 break; 4167 } 4168 } 4169 } 4170 if ((ent == NULL) || (ent->ent_lu != lu) || 4171 (ent->ent_itl_datap == NULL)) { 4172 rw_exit(iss->iss_lockp); 4173 return (STMF_NOT_FOUND); 4174 } 4175 itl = ent->ent_itl_datap; 4176 ent->ent_itl_datap = NULL; 4177 rw_exit(iss->iss_lockp); 4178 stmf_do_itl_dereg(lu, itl, STMF_ITL_REASON_DEREG_REQUEST); 4179 4180 return (STMF_SUCCESS); 4181 } 4182 4183 stmf_status_t 4184 stmf_get_itl_handle(stmf_lu_t *lu, uint8_t *lun, stmf_scsi_session_t *ss, 4185 uint64_t session_id, void **itl_handle_retp) 4186 { 4187 stmf_i_scsi_session_t *iss; 4188 stmf_lun_map_ent_t *ent; 4189 stmf_lun_map_t *lm; 4190 stmf_status_t ret; 4191 int i; 4192 uint16_t n; 4193 4194 if (ss == NULL) { 4195 iss = stmf_session_id_to_issptr(session_id, 1); 4196 if (iss == NULL) 4197 return (STMF_NOT_FOUND); 4198 } else { 4199 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private; 4200 rw_enter(iss->iss_lockp, RW_WRITER); 4201 } 4202 4203 ent = NULL; 4204 if (lun == NULL) { 4205 lm = iss->iss_sm; 4206 for (i = 0; i < lm->lm_nentries; i++) { 4207 if (lm->lm_plus[i] == NULL) 4208 continue; 4209 ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 4210 if (ent->ent_lu == lu) 4211 break; 4212 } 4213 } else { 4214 n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8)); 4215 ent = (stmf_lun_map_ent_t *) 4216 stmf_get_ent_from_map(iss->iss_sm, n); 4217 if (lu && (ent->ent_lu != lu)) 4218 ent = NULL; 4219 } 4220 if (ent && ent->ent_itl_datap) { 4221 *itl_handle_retp = ent->ent_itl_datap->itl_handle; 4222 ret = STMF_SUCCESS; 4223 } else { 4224 ret = STMF_NOT_FOUND; 4225 } 4226 4227 rw_exit(iss->iss_lockp); 4228 return (ret); 4229 } 4230 4231 stmf_data_buf_t * 4232 stmf_alloc_dbuf(scsi_task_t *task, uint32_t size, uint32_t *pminsize, 4233 uint32_t flags) 4234 { 4235 stmf_i_scsi_task_t *itask = 4236 (stmf_i_scsi_task_t *)task->task_stmf_private; 4237 stmf_local_port_t *lport = task->task_lport; 4238 stmf_data_buf_t *dbuf; 4239 uint8_t ndx; 4240 4241 ndx = stmf_first_zero[itask->itask_allocated_buf_map]; 4242 if (ndx == 0xff) 4243 return (NULL); 4244 dbuf = itask->itask_dbufs[ndx] = lport->lport_ds->ds_alloc_data_buf( 4245 task, size, pminsize, flags); 4246 if (dbuf) { 4247 task->task_cur_nbufs++; 4248 itask->itask_allocated_buf_map |= (1 << ndx); 4249 dbuf->db_handle = ndx; 4250 return (dbuf); 4251 } 4252 4253 return (NULL); 4254 } 4255 4256 stmf_status_t 4257 stmf_setup_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t flags) 4258 { 4259 stmf_i_scsi_task_t *itask = 4260 (stmf_i_scsi_task_t *)task->task_stmf_private; 4261 stmf_local_port_t *lport = task->task_lport; 4262 uint8_t ndx; 4263 stmf_status_t ret; 4264 4265 ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF); 4266 ASSERT(lport->lport_ds->ds_setup_dbuf != NULL); 4267 ASSERT(dbuf->db_flags & DB_LU_DATA_BUF); 4268 4269 if ((task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF) == 0) 4270 return (STMF_FAILURE); 4271 if (lport->lport_ds->ds_setup_dbuf == NULL) 4272 return (STMF_FAILURE); 4273 4274 ndx = stmf_first_zero[itask->itask_allocated_buf_map]; 4275 if (ndx == 0xff) 4276 return (STMF_FAILURE); 4277 ret = lport->lport_ds->ds_setup_dbuf(task, dbuf, flags); 4278 if (ret == STMF_FAILURE) 4279 return (STMF_FAILURE); 4280 itask->itask_dbufs[ndx] = dbuf; 4281 task->task_cur_nbufs++; 4282 itask->itask_allocated_buf_map |= (1 << ndx); 4283 dbuf->db_handle = ndx; 4284 4285 return (STMF_SUCCESS); 4286 } 4287 4288 void 4289 stmf_teardown_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf) 4290 { 4291 stmf_i_scsi_task_t *itask = 4292 (stmf_i_scsi_task_t *)task->task_stmf_private; 4293 stmf_local_port_t *lport = task->task_lport; 4294 4295 ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF); 4296 ASSERT(lport->lport_ds->ds_teardown_dbuf != NULL); 4297 ASSERT(dbuf->db_flags & DB_LU_DATA_BUF); 4298 4299 itask->itask_allocated_buf_map &= ~(1 << dbuf->db_handle); 4300 task->task_cur_nbufs--; 4301 lport->lport_ds->ds_teardown_dbuf(lport->lport_ds, dbuf); 4302 } 4303 4304 void 4305 stmf_free_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf) 4306 { 4307 stmf_i_scsi_task_t *itask = 4308 (stmf_i_scsi_task_t *)task->task_stmf_private; 4309 stmf_local_port_t *lport = task->task_lport; 4310 4311 itask->itask_allocated_buf_map &= ~(1 << dbuf->db_handle); 4312 task->task_cur_nbufs--; 4313 lport->lport_ds->ds_free_data_buf(lport->lport_ds, dbuf); 4314 } 4315 4316 stmf_data_buf_t * 4317 stmf_handle_to_buf(scsi_task_t *task, uint8_t h) 4318 { 4319 stmf_i_scsi_task_t *itask; 4320 4321 itask = (stmf_i_scsi_task_t *)task->task_stmf_private; 4322 if (h > 3) 4323 return (NULL); 4324 return (itask->itask_dbufs[h]); 4325 } 4326 4327 /* ARGSUSED */ 4328 struct scsi_task * 4329 stmf_task_alloc(struct stmf_local_port *lport, stmf_scsi_session_t *ss, 4330 uint8_t *lun, uint16_t cdb_length_in, uint16_t ext_id) 4331 { 4332 stmf_lu_t *lu; 4333 stmf_i_scsi_session_t *iss; 4334 stmf_i_lu_t *ilu; 4335 stmf_i_scsi_task_t *itask; 4336 stmf_i_scsi_task_t **ppitask; 4337 scsi_task_t *task; 4338 uint8_t *l; 4339 stmf_lun_map_ent_t *lun_map_ent; 4340 uint16_t cdb_length; 4341 uint16_t luNbr; 4342 uint8_t new_task = 0; 4343 4344 /* 4345 * We allocate 7 extra bytes for CDB to provide a cdb pointer which 4346 * is guaranteed to be 8 byte aligned. Some LU providers like OSD 4347 * depend upon this alignment. 4348 */ 4349 if (cdb_length_in >= 16) 4350 cdb_length = cdb_length_in + 7; 4351 else 4352 cdb_length = 16 + 7; 4353 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private; 4354 luNbr = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8)); 4355 rw_enter(iss->iss_lockp, RW_READER); 4356 lun_map_ent = 4357 (stmf_lun_map_ent_t *)stmf_get_ent_from_map(iss->iss_sm, luNbr); 4358 if (!lun_map_ent) { 4359 lu = dlun0; 4360 } else { 4361 lu = lun_map_ent->ent_lu; 4362 } 4363 ilu = lu->lu_stmf_private; 4364 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 4365 rw_exit(iss->iss_lockp); 4366 return (NULL); 4367 } 4368 do { 4369 if (ilu->ilu_free_tasks == NULL) { 4370 new_task = 1; 4371 break; 4372 } 4373 mutex_enter(&ilu->ilu_task_lock); 4374 for (ppitask = &ilu->ilu_free_tasks; (*ppitask != NULL) && 4375 ((*ppitask)->itask_cdb_buf_size < cdb_length); 4376 ppitask = &((*ppitask)->itask_lu_free_next)) 4377 ; 4378 if (*ppitask) { 4379 itask = *ppitask; 4380 *ppitask = (*ppitask)->itask_lu_free_next; 4381 ilu->ilu_ntasks_free--; 4382 if (ilu->ilu_ntasks_free < ilu->ilu_ntasks_min_free) 4383 ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free; 4384 } else { 4385 new_task = 1; 4386 } 4387 mutex_exit(&ilu->ilu_task_lock); 4388 /* CONSTCOND */ 4389 } while (0); 4390 4391 if (!new_task) { 4392 /* 4393 * Save the task_cdb pointer and zero per cmd fields. 4394 * We know the task_cdb_length is large enough by task 4395 * selection process above. 4396 */ 4397 uint8_t *save_cdb; 4398 uintptr_t t_start, t_end; 4399 4400 task = itask->itask_task; 4401 save_cdb = task->task_cdb; /* save */ 4402 t_start = (uintptr_t)&task->task_flags; 4403 t_end = (uintptr_t)&task->task_extended_cmd; 4404 bzero((void *)t_start, (size_t)(t_end - t_start)); 4405 task->task_cdb = save_cdb; /* restore */ 4406 itask->itask_ncmds = 0; 4407 } else { 4408 task = (scsi_task_t *)stmf_alloc(STMF_STRUCT_SCSI_TASK, 4409 cdb_length, AF_FORCE_NOSLEEP); 4410 if (task == NULL) { 4411 rw_exit(iss->iss_lockp); 4412 return (NULL); 4413 } 4414 task->task_lu = lu; 4415 l = task->task_lun_no; 4416 l[0] = lun[0]; 4417 l[1] = lun[1]; 4418 l[2] = lun[2]; 4419 l[3] = lun[3]; 4420 l[4] = lun[4]; 4421 l[5] = lun[5]; 4422 l[6] = lun[6]; 4423 l[7] = lun[7]; 4424 task->task_cdb = (uint8_t *)task->task_port_private; 4425 if ((ulong_t)(task->task_cdb) & 7ul) { 4426 task->task_cdb = (uint8_t *)(((ulong_t) 4427 (task->task_cdb) + 7ul) & ~(7ul)); 4428 } 4429 itask = (stmf_i_scsi_task_t *)task->task_stmf_private; 4430 itask->itask_cdb_buf_size = cdb_length; 4431 } 4432 task->task_session = ss; 4433 task->task_lport = lport; 4434 task->task_cdb_length = cdb_length_in; 4435 itask->itask_flags = ITASK_IN_TRANSITION; 4436 itask->itask_waitq_time = 0; 4437 itask->itask_lu_read_time = itask->itask_lu_write_time = 0; 4438 itask->itask_lport_read_time = itask->itask_lport_write_time = 0; 4439 itask->itask_read_xfer = itask->itask_write_xfer = 0; 4440 4441 if (new_task) { 4442 if (lu->lu_task_alloc(task) != STMF_SUCCESS) { 4443 rw_exit(iss->iss_lockp); 4444 stmf_free(task); 4445 return (NULL); 4446 } 4447 mutex_enter(&ilu->ilu_task_lock); 4448 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 4449 mutex_exit(&ilu->ilu_task_lock); 4450 rw_exit(iss->iss_lockp); 4451 stmf_free(task); 4452 return (NULL); 4453 } 4454 itask->itask_lu_next = ilu->ilu_tasks; 4455 if (ilu->ilu_tasks) 4456 ilu->ilu_tasks->itask_lu_prev = itask; 4457 ilu->ilu_tasks = itask; 4458 /* kmem_zalloc automatically makes itask->itask_lu_prev NULL */ 4459 ilu->ilu_ntasks++; 4460 mutex_exit(&ilu->ilu_task_lock); 4461 } 4462 4463 itask->itask_ilu_task_cntr = ilu->ilu_cur_task_cntr; 4464 atomic_add_32(itask->itask_ilu_task_cntr, 1); 4465 itask->itask_start_time = ddi_get_lbolt(); 4466 4467 if ((lun_map_ent != NULL) && ((itask->itask_itl_datap = 4468 lun_map_ent->ent_itl_datap) != NULL)) { 4469 atomic_add_32(&itask->itask_itl_datap->itl_counter, 1); 4470 task->task_lu_itl_handle = itask->itask_itl_datap->itl_handle; 4471 } else { 4472 itask->itask_itl_datap = NULL; 4473 task->task_lu_itl_handle = NULL; 4474 } 4475 4476 rw_exit(iss->iss_lockp); 4477 return (task); 4478 } 4479 4480 static void 4481 stmf_task_lu_free(scsi_task_t *task, stmf_i_scsi_session_t *iss) 4482 { 4483 stmf_i_scsi_task_t *itask = 4484 (stmf_i_scsi_task_t *)task->task_stmf_private; 4485 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 4486 4487 ASSERT(rw_lock_held(iss->iss_lockp)); 4488 itask->itask_flags = ITASK_IN_FREE_LIST; 4489 itask->itask_proxy_msg_id = 0; 4490 mutex_enter(&ilu->ilu_task_lock); 4491 itask->itask_lu_free_next = ilu->ilu_free_tasks; 4492 ilu->ilu_free_tasks = itask; 4493 ilu->ilu_ntasks_free++; 4494 mutex_exit(&ilu->ilu_task_lock); 4495 atomic_add_32(itask->itask_ilu_task_cntr, -1); 4496 } 4497 4498 void 4499 stmf_task_lu_check_freelist(stmf_i_lu_t *ilu) 4500 { 4501 uint32_t num_to_release, ndx; 4502 stmf_i_scsi_task_t *itask; 4503 stmf_lu_t *lu = ilu->ilu_lu; 4504 4505 ASSERT(ilu->ilu_ntasks_min_free <= ilu->ilu_ntasks_free); 4506 4507 /* free half of the minimal free of the free tasks */ 4508 num_to_release = (ilu->ilu_ntasks_min_free + 1) / 2; 4509 if (!num_to_release) { 4510 return; 4511 } 4512 for (ndx = 0; ndx < num_to_release; ndx++) { 4513 mutex_enter(&ilu->ilu_task_lock); 4514 itask = ilu->ilu_free_tasks; 4515 if (itask == NULL) { 4516 mutex_exit(&ilu->ilu_task_lock); 4517 break; 4518 } 4519 ilu->ilu_free_tasks = itask->itask_lu_free_next; 4520 ilu->ilu_ntasks_free--; 4521 mutex_exit(&ilu->ilu_task_lock); 4522 4523 lu->lu_task_free(itask->itask_task); 4524 mutex_enter(&ilu->ilu_task_lock); 4525 if (itask->itask_lu_next) 4526 itask->itask_lu_next->itask_lu_prev = 4527 itask->itask_lu_prev; 4528 if (itask->itask_lu_prev) 4529 itask->itask_lu_prev->itask_lu_next = 4530 itask->itask_lu_next; 4531 else 4532 ilu->ilu_tasks = itask->itask_lu_next; 4533 4534 ilu->ilu_ntasks--; 4535 mutex_exit(&ilu->ilu_task_lock); 4536 stmf_free(itask->itask_task); 4537 } 4538 } 4539 4540 /* 4541 * Called with stmf_lock held 4542 */ 4543 void 4544 stmf_check_freetask() 4545 { 4546 stmf_i_lu_t *ilu; 4547 clock_t endtime = ddi_get_lbolt() + drv_usectohz(10000); 4548 4549 /* stmf_svc_ilu_draining may get changed after stmf_lock is released */ 4550 while ((ilu = stmf_state.stmf_svc_ilu_draining) != NULL) { 4551 stmf_state.stmf_svc_ilu_draining = ilu->ilu_next; 4552 if (!ilu->ilu_ntasks_min_free) { 4553 ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free; 4554 continue; 4555 } 4556 ilu->ilu_flags |= ILU_STALL_DEREGISTER; 4557 mutex_exit(&stmf_state.stmf_lock); 4558 stmf_task_lu_check_freelist(ilu); 4559 /* 4560 * we do not care about the accuracy of 4561 * ilu_ntasks_min_free, so we don't lock here 4562 */ 4563 ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free; 4564 mutex_enter(&stmf_state.stmf_lock); 4565 ilu->ilu_flags &= ~ILU_STALL_DEREGISTER; 4566 cv_broadcast(&stmf_state.stmf_cv); 4567 if (ddi_get_lbolt() >= endtime) 4568 break; 4569 } 4570 } 4571 4572 void 4573 stmf_do_ilu_timeouts(stmf_i_lu_t *ilu) 4574 { 4575 clock_t l = ddi_get_lbolt(); 4576 clock_t ps = drv_usectohz(1000000); 4577 stmf_i_scsi_task_t *itask; 4578 scsi_task_t *task; 4579 uint32_t to; 4580 4581 mutex_enter(&ilu->ilu_task_lock); 4582 for (itask = ilu->ilu_tasks; itask != NULL; 4583 itask = itask->itask_lu_next) { 4584 if (itask->itask_flags & (ITASK_IN_FREE_LIST | 4585 ITASK_BEING_ABORTED)) { 4586 continue; 4587 } 4588 task = itask->itask_task; 4589 if (task->task_timeout == 0) 4590 to = stmf_default_task_timeout; 4591 else 4592 to = task->task_timeout; 4593 if ((itask->itask_start_time + (to * ps)) > l) 4594 continue; 4595 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 4596 STMF_TIMEOUT, NULL); 4597 } 4598 mutex_exit(&ilu->ilu_task_lock); 4599 } 4600 4601 /* 4602 * Called with stmf_lock held 4603 */ 4604 void 4605 stmf_check_ilu_timing() 4606 { 4607 stmf_i_lu_t *ilu; 4608 clock_t endtime = ddi_get_lbolt() + drv_usectohz(10000); 4609 4610 /* stmf_svc_ilu_timing may get changed after stmf_lock is released */ 4611 while ((ilu = stmf_state.stmf_svc_ilu_timing) != NULL) { 4612 stmf_state.stmf_svc_ilu_timing = ilu->ilu_next; 4613 if (ilu->ilu_cur_task_cntr == (&ilu->ilu_task_cntr1)) { 4614 if (ilu->ilu_task_cntr2 == 0) { 4615 ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr2; 4616 continue; 4617 } 4618 } else { 4619 if (ilu->ilu_task_cntr1 == 0) { 4620 ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1; 4621 continue; 4622 } 4623 } 4624 /* 4625 * If we are here then it means that there is some slowdown 4626 * in tasks on this lu. We need to check. 4627 */ 4628 ilu->ilu_flags |= ILU_STALL_DEREGISTER; 4629 mutex_exit(&stmf_state.stmf_lock); 4630 stmf_do_ilu_timeouts(ilu); 4631 mutex_enter(&stmf_state.stmf_lock); 4632 ilu->ilu_flags &= ~ILU_STALL_DEREGISTER; 4633 cv_broadcast(&stmf_state.stmf_cv); 4634 if (ddi_get_lbolt() >= endtime) 4635 break; 4636 } 4637 } 4638 4639 /* 4640 * Kills all tasks on a lu except tm_task 4641 */ 4642 void 4643 stmf_task_lu_killall(stmf_lu_t *lu, scsi_task_t *tm_task, stmf_status_t s) 4644 { 4645 stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 4646 stmf_i_scsi_task_t *itask; 4647 4648 mutex_enter(&ilu->ilu_task_lock); 4649 4650 for (itask = ilu->ilu_tasks; itask != NULL; 4651 itask = itask->itask_lu_next) { 4652 if (itask->itask_flags & ITASK_IN_FREE_LIST) 4653 continue; 4654 if (itask->itask_task == tm_task) 4655 continue; 4656 stmf_abort(STMF_QUEUE_TASK_ABORT, itask->itask_task, s, NULL); 4657 } 4658 mutex_exit(&ilu->ilu_task_lock); 4659 } 4660 4661 void 4662 stmf_free_task_bufs(stmf_i_scsi_task_t *itask, stmf_local_port_t *lport) 4663 { 4664 int i; 4665 uint8_t map; 4666 4667 if ((map = itask->itask_allocated_buf_map) == 0) 4668 return; 4669 for (i = 0; i < 4; i++) { 4670 if (map & 1) { 4671 stmf_data_buf_t *dbuf; 4672 4673 dbuf = itask->itask_dbufs[i]; 4674 if (dbuf->db_xfer_start_timestamp) { 4675 stmf_lport_xfer_done(itask, dbuf); 4676 } 4677 if (dbuf->db_flags & DB_LU_DATA_BUF) { 4678 /* 4679 * LU needs to clean up buffer. 4680 * LU is required to free the buffer 4681 * in the xfer_done handler. 4682 */ 4683 scsi_task_t *task = itask->itask_task; 4684 stmf_lu_t *lu = task->task_lu; 4685 4686 lu->lu_dbuf_free(task, dbuf); 4687 ASSERT(((itask->itask_allocated_buf_map>>i) 4688 & 1) == 0); /* must be gone */ 4689 } else { 4690 ASSERT(dbuf->db_lu_private == NULL); 4691 dbuf->db_lu_private = NULL; 4692 lport->lport_ds->ds_free_data_buf( 4693 lport->lport_ds, dbuf); 4694 } 4695 } 4696 map >>= 1; 4697 } 4698 itask->itask_allocated_buf_map = 0; 4699 } 4700 4701 void 4702 stmf_task_free(scsi_task_t *task) 4703 { 4704 stmf_local_port_t *lport = task->task_lport; 4705 stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *) 4706 task->task_stmf_private; 4707 stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *) 4708 task->task_session->ss_stmf_private; 4709 4710 stmf_free_task_bufs(itask, lport); 4711 stmf_itl_task_done(itask); 4712 DTRACE_PROBE2(stmf__task__end, scsi_task_t *, task, 4713 hrtime_t, 4714 itask->itask_done_timestamp - itask->itask_start_timestamp); 4715 if (itask->itask_itl_datap) { 4716 if (atomic_add_32_nv(&itask->itask_itl_datap->itl_counter, 4717 -1) == 0) { 4718 stmf_release_itl_handle(task->task_lu, 4719 itask->itask_itl_datap); 4720 } 4721 } 4722 4723 rw_enter(iss->iss_lockp, RW_READER); 4724 lport->lport_task_free(task); 4725 if (itask->itask_worker) { 4726 atomic_add_32(&stmf_cur_ntasks, -1); 4727 atomic_add_32(&itask->itask_worker->worker_ref_count, -1); 4728 } 4729 /* 4730 * After calling stmf_task_lu_free, the task pointer can no longer 4731 * be trusted. 4732 */ 4733 stmf_task_lu_free(task, iss); 4734 rw_exit(iss->iss_lockp); 4735 } 4736 4737 void 4738 stmf_post_task(scsi_task_t *task, stmf_data_buf_t *dbuf) 4739 { 4740 stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *) 4741 task->task_stmf_private; 4742 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 4743 int nv; 4744 uint32_t old, new; 4745 uint32_t ct; 4746 stmf_worker_t *w, *w1; 4747 uint8_t tm; 4748 4749 if (task->task_max_nbufs > 4) 4750 task->task_max_nbufs = 4; 4751 task->task_cur_nbufs = 0; 4752 /* Latest value of currently running tasks */ 4753 ct = atomic_add_32_nv(&stmf_cur_ntasks, 1); 4754 4755 /* Select the next worker using round robin */ 4756 nv = (int)atomic_add_32_nv((uint32_t *)&stmf_worker_sel_counter, 1); 4757 if (nv >= stmf_nworkers_accepting_cmds) { 4758 int s = nv; 4759 do { 4760 nv -= stmf_nworkers_accepting_cmds; 4761 } while (nv >= stmf_nworkers_accepting_cmds); 4762 if (nv < 0) 4763 nv = 0; 4764 /* Its ok if this cas fails */ 4765 (void) atomic_cas_32((uint32_t *)&stmf_worker_sel_counter, 4766 s, nv); 4767 } 4768 w = &stmf_workers[nv]; 4769 4770 /* 4771 * A worker can be pinned by interrupt. So select the next one 4772 * if it has lower load. 4773 */ 4774 if ((nv + 1) >= stmf_nworkers_accepting_cmds) { 4775 w1 = stmf_workers; 4776 } else { 4777 w1 = &stmf_workers[nv + 1]; 4778 } 4779 if (w1->worker_queue_depth < w->worker_queue_depth) 4780 w = w1; 4781 4782 mutex_enter(&w->worker_lock); 4783 if (((w->worker_flags & STMF_WORKER_STARTED) == 0) || 4784 (w->worker_flags & STMF_WORKER_TERMINATE)) { 4785 /* 4786 * Maybe we are in the middle of a change. Just go to 4787 * the 1st worker. 4788 */ 4789 mutex_exit(&w->worker_lock); 4790 w = stmf_workers; 4791 mutex_enter(&w->worker_lock); 4792 } 4793 itask->itask_worker = w; 4794 /* 4795 * Track max system load inside the worker as we already have the 4796 * worker lock (no point implementing another lock). The service 4797 * thread will do the comparisons and figure out the max overall 4798 * system load. 4799 */ 4800 if (w->worker_max_sys_qdepth_pu < ct) 4801 w->worker_max_sys_qdepth_pu = ct; 4802 4803 do { 4804 old = new = itask->itask_flags; 4805 new |= ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE; 4806 if (task->task_mgmt_function) { 4807 tm = task->task_mgmt_function; 4808 if ((tm == TM_TARGET_RESET) || 4809 (tm == TM_TARGET_COLD_RESET) || 4810 (tm == TM_TARGET_WARM_RESET)) { 4811 new |= ITASK_DEFAULT_HANDLING; 4812 } 4813 } else if (task->task_cdb[0] == SCMD_REPORT_LUNS) { 4814 new |= ITASK_DEFAULT_HANDLING; 4815 } 4816 new &= ~ITASK_IN_TRANSITION; 4817 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 4818 4819 stmf_itl_task_start(itask); 4820 4821 itask->itask_worker_next = NULL; 4822 if (w->worker_task_tail) { 4823 w->worker_task_tail->itask_worker_next = itask; 4824 } else { 4825 w->worker_task_head = itask; 4826 } 4827 w->worker_task_tail = itask; 4828 if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) { 4829 w->worker_max_qdepth_pu = w->worker_queue_depth; 4830 } 4831 /* Measure task waitq time */ 4832 itask->itask_waitq_enter_timestamp = gethrtime(); 4833 atomic_add_32(&w->worker_ref_count, 1); 4834 itask->itask_cmd_stack[0] = ITASK_CMD_NEW_TASK; 4835 itask->itask_ncmds = 1; 4836 if (dbuf) { 4837 itask->itask_allocated_buf_map = 1; 4838 itask->itask_dbufs[0] = dbuf; 4839 dbuf->db_handle = 0; 4840 } else { 4841 itask->itask_allocated_buf_map = 0; 4842 itask->itask_dbufs[0] = NULL; 4843 } 4844 4845 if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) { 4846 w->worker_signal_timestamp = gethrtime(); 4847 DTRACE_PROBE2(worker__signal, stmf_worker_t *, w, 4848 scsi_task_t *, task); 4849 cv_signal(&w->worker_cv); 4850 } 4851 mutex_exit(&w->worker_lock); 4852 4853 /* 4854 * This can only happen if during stmf_task_alloc(), ILU_RESET_ACTIVE 4855 * was set between checking of ILU_RESET_ACTIVE and clearing of the 4856 * ITASK_IN_FREE_LIST flag. Take care of these "sneaked-in" tasks here. 4857 */ 4858 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 4859 stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ABORTED, NULL); 4860 } 4861 } 4862 4863 /* 4864 * ++++++++++++++ ABORT LOGIC ++++++++++++++++++++ 4865 * Once ITASK_BEING_ABORTED is set, ITASK_KNOWN_TO_LU can be reset already 4866 * i.e. before ITASK_BEING_ABORTED being set. But if it was not, it cannot 4867 * be reset until the LU explicitly calls stmf_task_lu_aborted(). Of course 4868 * the LU will make this call only if we call the LU's abort entry point. 4869 * we will only call that entry point if ITASK_KNOWN_TO_LU was set. 4870 * 4871 * Same logic applies for the port. 4872 * 4873 * Also ITASK_BEING_ABORTED will not be allowed to set if both KNOWN_TO_LU 4874 * and KNOWN_TO_TGT_PORT are reset. 4875 * 4876 * +++++++++++++++++++++++++++++++++++++++++++++++ 4877 */ 4878 4879 stmf_status_t 4880 stmf_xfer_data(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t ioflags) 4881 { 4882 stmf_status_t ret; 4883 4884 stmf_i_scsi_task_t *itask = 4885 (stmf_i_scsi_task_t *)task->task_stmf_private; 4886 4887 if (ioflags & STMF_IOF_LU_DONE) { 4888 uint32_t new, old; 4889 do { 4890 new = old = itask->itask_flags; 4891 if (new & ITASK_BEING_ABORTED) 4892 return (STMF_ABORTED); 4893 new &= ~ITASK_KNOWN_TO_LU; 4894 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 4895 } 4896 if (itask->itask_flags & ITASK_BEING_ABORTED) 4897 return (STMF_ABORTED); 4898 #ifdef DEBUG 4899 if (!(ioflags & STMF_IOF_STATS_ONLY) && stmf_drop_buf_counter > 0) { 4900 if (atomic_add_32_nv((uint32_t *)&stmf_drop_buf_counter, -1) == 4901 1) 4902 return (STMF_SUCCESS); 4903 } 4904 #endif 4905 4906 stmf_update_kstat_lu_io(task, dbuf); 4907 stmf_update_kstat_lport_io(task, dbuf); 4908 stmf_lport_xfer_start(itask, dbuf); 4909 if (ioflags & STMF_IOF_STATS_ONLY) { 4910 stmf_lport_xfer_done(itask, dbuf); 4911 return (STMF_SUCCESS); 4912 } 4913 4914 ret = task->task_lport->lport_xfer_data(task, dbuf, ioflags); 4915 4916 /* 4917 * Port provider may have already called the buffer callback in 4918 * which case dbuf->db_xfer_start_timestamp will be 0. 4919 */ 4920 if ((ret != STMF_SUCCESS) && (dbuf->db_xfer_start_timestamp != 0)) { 4921 stmf_lport_xfer_done(itask, dbuf); 4922 } 4923 4924 return (ret); 4925 } 4926 4927 void 4928 stmf_data_xfer_done(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t iof) 4929 { 4930 stmf_i_scsi_task_t *itask = 4931 (stmf_i_scsi_task_t *)task->task_stmf_private; 4932 stmf_worker_t *w = itask->itask_worker; 4933 uint32_t new, old; 4934 uint8_t update_queue_flags, free_it, queue_it; 4935 4936 stmf_lport_xfer_done(itask, dbuf); 4937 4938 mutex_enter(&w->worker_lock); 4939 do { 4940 new = old = itask->itask_flags; 4941 if (old & ITASK_BEING_ABORTED) { 4942 mutex_exit(&w->worker_lock); 4943 return; 4944 } 4945 free_it = 0; 4946 if (iof & STMF_IOF_LPORT_DONE) { 4947 new &= ~ITASK_KNOWN_TO_TGT_PORT; 4948 task->task_completion_status = dbuf->db_xfer_status; 4949 free_it = 1; 4950 } 4951 /* 4952 * If the task is known to LU then queue it. But if 4953 * it is already queued (multiple completions) then 4954 * just update the buffer information by grabbing the 4955 * worker lock. If the task is not known to LU, 4956 * completed/aborted, then see if we need to 4957 * free this task. 4958 */ 4959 if (old & ITASK_KNOWN_TO_LU) { 4960 free_it = 0; 4961 update_queue_flags = 1; 4962 if (old & ITASK_IN_WORKER_QUEUE) { 4963 queue_it = 0; 4964 } else { 4965 queue_it = 1; 4966 new |= ITASK_IN_WORKER_QUEUE; 4967 } 4968 } else { 4969 update_queue_flags = 0; 4970 queue_it = 0; 4971 } 4972 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 4973 4974 if (update_queue_flags) { 4975 uint8_t cmd = (dbuf->db_handle << 5) | ITASK_CMD_DATA_XFER_DONE; 4976 4977 ASSERT(itask->itask_ncmds < ITASK_MAX_NCMDS); 4978 itask->itask_cmd_stack[itask->itask_ncmds++] = cmd; 4979 if (queue_it) { 4980 itask->itask_worker_next = NULL; 4981 if (w->worker_task_tail) { 4982 w->worker_task_tail->itask_worker_next = itask; 4983 } else { 4984 w->worker_task_head = itask; 4985 } 4986 w->worker_task_tail = itask; 4987 /* Measure task waitq time */ 4988 itask->itask_waitq_enter_timestamp = gethrtime(); 4989 if (++(w->worker_queue_depth) > 4990 w->worker_max_qdepth_pu) { 4991 w->worker_max_qdepth_pu = w->worker_queue_depth; 4992 } 4993 if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) 4994 cv_signal(&w->worker_cv); 4995 } 4996 } 4997 mutex_exit(&w->worker_lock); 4998 4999 if (free_it) { 5000 if ((itask->itask_flags & (ITASK_KNOWN_TO_LU | 5001 ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE | 5002 ITASK_BEING_ABORTED)) == 0) { 5003 stmf_task_free(task); 5004 } 5005 } 5006 } 5007 5008 stmf_status_t 5009 stmf_send_scsi_status(scsi_task_t *task, uint32_t ioflags) 5010 { 5011 DTRACE_PROBE1(scsi__send__status, scsi_task_t *, task); 5012 5013 stmf_i_scsi_task_t *itask = 5014 (stmf_i_scsi_task_t *)task->task_stmf_private; 5015 if (ioflags & STMF_IOF_LU_DONE) { 5016 uint32_t new, old; 5017 do { 5018 new = old = itask->itask_flags; 5019 if (new & ITASK_BEING_ABORTED) 5020 return (STMF_ABORTED); 5021 new &= ~ITASK_KNOWN_TO_LU; 5022 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 5023 } 5024 5025 if (!(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT)) { 5026 return (STMF_SUCCESS); 5027 } 5028 5029 if (itask->itask_flags & ITASK_BEING_ABORTED) 5030 return (STMF_ABORTED); 5031 5032 if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) { 5033 task->task_status_ctrl = 0; 5034 task->task_resid = 0; 5035 } else if (task->task_cmd_xfer_length > 5036 task->task_expected_xfer_length) { 5037 task->task_status_ctrl = TASK_SCTRL_OVER; 5038 task->task_resid = task->task_cmd_xfer_length - 5039 task->task_expected_xfer_length; 5040 } else if (task->task_nbytes_transferred < 5041 task->task_expected_xfer_length) { 5042 task->task_status_ctrl = TASK_SCTRL_UNDER; 5043 task->task_resid = task->task_expected_xfer_length - 5044 task->task_nbytes_transferred; 5045 } else { 5046 task->task_status_ctrl = 0; 5047 task->task_resid = 0; 5048 } 5049 return (task->task_lport->lport_send_status(task, ioflags)); 5050 } 5051 5052 void 5053 stmf_send_status_done(scsi_task_t *task, stmf_status_t s, uint32_t iof) 5054 { 5055 stmf_i_scsi_task_t *itask = 5056 (stmf_i_scsi_task_t *)task->task_stmf_private; 5057 stmf_worker_t *w = itask->itask_worker; 5058 uint32_t new, old; 5059 uint8_t free_it, queue_it; 5060 5061 mutex_enter(&w->worker_lock); 5062 do { 5063 new = old = itask->itask_flags; 5064 if (old & ITASK_BEING_ABORTED) { 5065 mutex_exit(&w->worker_lock); 5066 return; 5067 } 5068 free_it = 0; 5069 if (iof & STMF_IOF_LPORT_DONE) { 5070 new &= ~ITASK_KNOWN_TO_TGT_PORT; 5071 free_it = 1; 5072 } 5073 /* 5074 * If the task is known to LU then queue it. But if 5075 * it is already queued (multiple completions) then 5076 * just update the buffer information by grabbing the 5077 * worker lock. If the task is not known to LU, 5078 * completed/aborted, then see if we need to 5079 * free this task. 5080 */ 5081 if (old & ITASK_KNOWN_TO_LU) { 5082 free_it = 0; 5083 queue_it = 1; 5084 if (old & ITASK_IN_WORKER_QUEUE) { 5085 cmn_err(CE_PANIC, "status completion received" 5086 " when task is already in worker queue " 5087 " task = %p", (void *)task); 5088 } 5089 new |= ITASK_IN_WORKER_QUEUE; 5090 } else { 5091 queue_it = 0; 5092 } 5093 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 5094 task->task_completion_status = s; 5095 5096 5097 if (queue_it) { 5098 ASSERT(itask->itask_ncmds < ITASK_MAX_NCMDS); 5099 itask->itask_cmd_stack[itask->itask_ncmds++] = 5100 ITASK_CMD_STATUS_DONE; 5101 itask->itask_worker_next = NULL; 5102 if (w->worker_task_tail) { 5103 w->worker_task_tail->itask_worker_next = itask; 5104 } else { 5105 w->worker_task_head = itask; 5106 } 5107 w->worker_task_tail = itask; 5108 /* Measure task waitq time */ 5109 itask->itask_waitq_enter_timestamp = gethrtime(); 5110 if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) { 5111 w->worker_max_qdepth_pu = w->worker_queue_depth; 5112 } 5113 if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) 5114 cv_signal(&w->worker_cv); 5115 } 5116 mutex_exit(&w->worker_lock); 5117 5118 if (free_it) { 5119 if ((itask->itask_flags & (ITASK_KNOWN_TO_LU | 5120 ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE | 5121 ITASK_BEING_ABORTED)) == 0) { 5122 stmf_task_free(task); 5123 } else { 5124 cmn_err(CE_PANIC, "LU is done with the task but LPORT " 5125 " is not done, itask %p itask_flags %x", 5126 (void *)itask, itask->itask_flags); 5127 } 5128 } 5129 } 5130 5131 void 5132 stmf_task_lu_done(scsi_task_t *task) 5133 { 5134 stmf_i_scsi_task_t *itask = 5135 (stmf_i_scsi_task_t *)task->task_stmf_private; 5136 stmf_worker_t *w = itask->itask_worker; 5137 uint32_t new, old; 5138 5139 mutex_enter(&w->worker_lock); 5140 do { 5141 new = old = itask->itask_flags; 5142 if (old & ITASK_BEING_ABORTED) { 5143 mutex_exit(&w->worker_lock); 5144 return; 5145 } 5146 if (old & ITASK_IN_WORKER_QUEUE) { 5147 cmn_err(CE_PANIC, "task_lu_done received" 5148 " when task is in worker queue " 5149 " task = %p", (void *)task); 5150 } 5151 new &= ~ITASK_KNOWN_TO_LU; 5152 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 5153 5154 mutex_exit(&w->worker_lock); 5155 5156 if ((itask->itask_flags & (ITASK_KNOWN_TO_LU | 5157 ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE | 5158 ITASK_BEING_ABORTED)) == 0) { 5159 stmf_task_free(task); 5160 } else { 5161 cmn_err(CE_PANIC, "stmf_lu_done should be the last stage but " 5162 " the task is still not done, task = %p", (void *)task); 5163 } 5164 } 5165 5166 void 5167 stmf_queue_task_for_abort(scsi_task_t *task, stmf_status_t s) 5168 { 5169 stmf_i_scsi_task_t *itask = 5170 (stmf_i_scsi_task_t *)task->task_stmf_private; 5171 stmf_worker_t *w; 5172 uint32_t old, new; 5173 5174 do { 5175 old = new = itask->itask_flags; 5176 if ((old & ITASK_BEING_ABORTED) || 5177 ((old & (ITASK_KNOWN_TO_TGT_PORT | 5178 ITASK_KNOWN_TO_LU)) == 0)) { 5179 return; 5180 } 5181 new |= ITASK_BEING_ABORTED; 5182 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 5183 task->task_completion_status = s; 5184 itask->itask_start_time = ddi_get_lbolt(); 5185 5186 if (((w = itask->itask_worker) == NULL) || 5187 (itask->itask_flags & ITASK_IN_TRANSITION)) { 5188 return; 5189 } 5190 5191 /* Queue it and get out */ 5192 mutex_enter(&w->worker_lock); 5193 if (itask->itask_flags & ITASK_IN_WORKER_QUEUE) { 5194 mutex_exit(&w->worker_lock); 5195 return; 5196 } 5197 atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE); 5198 itask->itask_worker_next = NULL; 5199 if (w->worker_task_tail) { 5200 w->worker_task_tail->itask_worker_next = itask; 5201 } else { 5202 w->worker_task_head = itask; 5203 } 5204 w->worker_task_tail = itask; 5205 if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) { 5206 w->worker_max_qdepth_pu = w->worker_queue_depth; 5207 } 5208 if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) 5209 cv_signal(&w->worker_cv); 5210 mutex_exit(&w->worker_lock); 5211 } 5212 5213 void 5214 stmf_abort(int abort_cmd, scsi_task_t *task, stmf_status_t s, void *arg) 5215 { 5216 stmf_i_scsi_task_t *itask = NULL; 5217 uint32_t old, new, f, rf; 5218 5219 DTRACE_PROBE2(scsi__task__abort, scsi_task_t *, task, 5220 stmf_status_t, s); 5221 5222 switch (abort_cmd) { 5223 case STMF_QUEUE_ABORT_LU: 5224 stmf_task_lu_killall((stmf_lu_t *)arg, task, s); 5225 return; 5226 case STMF_QUEUE_TASK_ABORT: 5227 stmf_queue_task_for_abort(task, s); 5228 return; 5229 case STMF_REQUEUE_TASK_ABORT_LPORT: 5230 rf = ITASK_TGT_PORT_ABORT_CALLED; 5231 f = ITASK_KNOWN_TO_TGT_PORT; 5232 break; 5233 case STMF_REQUEUE_TASK_ABORT_LU: 5234 rf = ITASK_LU_ABORT_CALLED; 5235 f = ITASK_KNOWN_TO_LU; 5236 break; 5237 default: 5238 return; 5239 } 5240 itask = (stmf_i_scsi_task_t *)task->task_stmf_private; 5241 f |= ITASK_BEING_ABORTED | rf; 5242 do { 5243 old = new = itask->itask_flags; 5244 if ((old & f) != f) { 5245 return; 5246 } 5247 new &= ~rf; 5248 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 5249 } 5250 5251 void 5252 stmf_task_lu_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof) 5253 { 5254 char info[STMF_CHANGE_INFO_LEN]; 5255 stmf_i_scsi_task_t *itask = TASK_TO_ITASK(task); 5256 unsigned long long st; 5257 5258 st = s; /* gcc fix */ 5259 if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) { 5260 (void) snprintf(info, sizeof (info), 5261 "task %p, lu failed to abort ret=%llx", (void *)task, st); 5262 } else if ((iof & STMF_IOF_LU_DONE) == 0) { 5263 (void) snprintf(info, sizeof (info), 5264 "Task aborted but LU is not finished, task =" 5265 "%p, s=%llx, iof=%x", (void *)task, st, iof); 5266 } else { 5267 /* 5268 * LU abort successfully 5269 */ 5270 atomic_and_32(&itask->itask_flags, ~ITASK_KNOWN_TO_LU); 5271 return; 5272 } 5273 5274 stmf_abort_task_offline(task, 1, info); 5275 } 5276 5277 void 5278 stmf_task_lport_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof) 5279 { 5280 char info[STMF_CHANGE_INFO_LEN]; 5281 stmf_i_scsi_task_t *itask = TASK_TO_ITASK(task); 5282 unsigned long long st; 5283 uint32_t old, new; 5284 5285 st = s; 5286 if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) { 5287 (void) snprintf(info, sizeof (info), 5288 "task %p, tgt port failed to abort ret=%llx", (void *)task, 5289 st); 5290 } else if ((iof & STMF_IOF_LPORT_DONE) == 0) { 5291 (void) snprintf(info, sizeof (info), 5292 "Task aborted but tgt port is not finished, " 5293 "task=%p, s=%llx, iof=%x", (void *)task, st, iof); 5294 } else { 5295 /* 5296 * LPORT abort successfully 5297 */ 5298 do { 5299 old = new = itask->itask_flags; 5300 if (!(old & ITASK_KNOWN_TO_TGT_PORT)) 5301 return; 5302 new &= ~ITASK_KNOWN_TO_TGT_PORT; 5303 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 5304 return; 5305 } 5306 5307 stmf_abort_task_offline(task, 0, info); 5308 } 5309 5310 stmf_status_t 5311 stmf_task_poll_lu(scsi_task_t *task, uint32_t timeout) 5312 { 5313 stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *) 5314 task->task_stmf_private; 5315 stmf_worker_t *w = itask->itask_worker; 5316 int i; 5317 5318 ASSERT(itask->itask_flags & ITASK_KNOWN_TO_LU); 5319 mutex_enter(&w->worker_lock); 5320 if (itask->itask_ncmds >= ITASK_MAX_NCMDS) { 5321 mutex_exit(&w->worker_lock); 5322 return (STMF_BUSY); 5323 } 5324 for (i = 0; i < itask->itask_ncmds; i++) { 5325 if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LU) { 5326 mutex_exit(&w->worker_lock); 5327 return (STMF_SUCCESS); 5328 } 5329 } 5330 itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LU; 5331 if (timeout == ITASK_DEFAULT_POLL_TIMEOUT) { 5332 itask->itask_poll_timeout = ddi_get_lbolt() + 1; 5333 } else { 5334 clock_t t = drv_usectohz(timeout * 1000); 5335 if (t == 0) 5336 t = 1; 5337 itask->itask_poll_timeout = ddi_get_lbolt() + t; 5338 } 5339 if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) { 5340 itask->itask_worker_next = NULL; 5341 if (w->worker_task_tail) { 5342 w->worker_task_tail->itask_worker_next = itask; 5343 } else { 5344 w->worker_task_head = itask; 5345 } 5346 w->worker_task_tail = itask; 5347 if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) { 5348 w->worker_max_qdepth_pu = w->worker_queue_depth; 5349 } 5350 atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE); 5351 if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) 5352 cv_signal(&w->worker_cv); 5353 } 5354 mutex_exit(&w->worker_lock); 5355 return (STMF_SUCCESS); 5356 } 5357 5358 stmf_status_t 5359 stmf_task_poll_lport(scsi_task_t *task, uint32_t timeout) 5360 { 5361 stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *) 5362 task->task_stmf_private; 5363 stmf_worker_t *w = itask->itask_worker; 5364 int i; 5365 5366 ASSERT(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT); 5367 mutex_enter(&w->worker_lock); 5368 if (itask->itask_ncmds >= ITASK_MAX_NCMDS) { 5369 mutex_exit(&w->worker_lock); 5370 return (STMF_BUSY); 5371 } 5372 for (i = 0; i < itask->itask_ncmds; i++) { 5373 if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LPORT) { 5374 mutex_exit(&w->worker_lock); 5375 return (STMF_SUCCESS); 5376 } 5377 } 5378 itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LPORT; 5379 if (timeout == ITASK_DEFAULT_POLL_TIMEOUT) { 5380 itask->itask_poll_timeout = ddi_get_lbolt() + 1; 5381 } else { 5382 clock_t t = drv_usectohz(timeout * 1000); 5383 if (t == 0) 5384 t = 1; 5385 itask->itask_poll_timeout = ddi_get_lbolt() + t; 5386 } 5387 if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) { 5388 itask->itask_worker_next = NULL; 5389 if (w->worker_task_tail) { 5390 w->worker_task_tail->itask_worker_next = itask; 5391 } else { 5392 w->worker_task_head = itask; 5393 } 5394 w->worker_task_tail = itask; 5395 if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) { 5396 w->worker_max_qdepth_pu = w->worker_queue_depth; 5397 } 5398 if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) 5399 cv_signal(&w->worker_cv); 5400 } 5401 mutex_exit(&w->worker_lock); 5402 return (STMF_SUCCESS); 5403 } 5404 5405 void 5406 stmf_do_task_abort(scsi_task_t *task) 5407 { 5408 stmf_i_scsi_task_t *itask = TASK_TO_ITASK(task); 5409 stmf_lu_t *lu; 5410 stmf_local_port_t *lport; 5411 unsigned long long ret; 5412 uint32_t old, new; 5413 uint8_t call_lu_abort, call_port_abort; 5414 char info[STMF_CHANGE_INFO_LEN]; 5415 5416 lu = task->task_lu; 5417 lport = task->task_lport; 5418 do { 5419 old = new = itask->itask_flags; 5420 if ((old & (ITASK_KNOWN_TO_LU | ITASK_LU_ABORT_CALLED)) == 5421 ITASK_KNOWN_TO_LU) { 5422 new |= ITASK_LU_ABORT_CALLED; 5423 call_lu_abort = 1; 5424 } else { 5425 call_lu_abort = 0; 5426 } 5427 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 5428 5429 if (call_lu_abort) { 5430 if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0) { 5431 ret = lu->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0); 5432 } else { 5433 ret = dlun0->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0); 5434 } 5435 if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) { 5436 stmf_task_lu_aborted(task, ret, STMF_IOF_LU_DONE); 5437 } else if (ret == STMF_BUSY) { 5438 atomic_and_32(&itask->itask_flags, 5439 ~ITASK_LU_ABORT_CALLED); 5440 } else if (ret != STMF_SUCCESS) { 5441 (void) snprintf(info, sizeof (info), 5442 "Abort failed by LU %p, ret %llx", (void *)lu, ret); 5443 stmf_abort_task_offline(task, 1, info); 5444 } 5445 } else if (itask->itask_flags & ITASK_KNOWN_TO_LU) { 5446 if (ddi_get_lbolt() > (itask->itask_start_time + 5447 STMF_SEC2TICK(lu->lu_abort_timeout? 5448 lu->lu_abort_timeout : ITASK_DEFAULT_ABORT_TIMEOUT))) { 5449 (void) snprintf(info, sizeof (info), 5450 "lu abort timed out"); 5451 stmf_abort_task_offline(itask->itask_task, 1, info); 5452 } 5453 } 5454 5455 do { 5456 old = new = itask->itask_flags; 5457 if ((old & (ITASK_KNOWN_TO_TGT_PORT | 5458 ITASK_TGT_PORT_ABORT_CALLED)) == ITASK_KNOWN_TO_TGT_PORT) { 5459 new |= ITASK_TGT_PORT_ABORT_CALLED; 5460 call_port_abort = 1; 5461 } else { 5462 call_port_abort = 0; 5463 } 5464 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 5465 if (call_port_abort) { 5466 ret = lport->lport_abort(lport, STMF_LPORT_ABORT_TASK, task, 0); 5467 if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) { 5468 stmf_task_lport_aborted(task, ret, STMF_IOF_LPORT_DONE); 5469 } else if (ret == STMF_BUSY) { 5470 atomic_and_32(&itask->itask_flags, 5471 ~ITASK_TGT_PORT_ABORT_CALLED); 5472 } else if (ret != STMF_SUCCESS) { 5473 (void) snprintf(info, sizeof (info), 5474 "Abort failed by tgt port %p ret %llx", 5475 (void *)lport, ret); 5476 stmf_abort_task_offline(task, 0, info); 5477 } 5478 } else if (itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT) { 5479 if (ddi_get_lbolt() > (itask->itask_start_time + 5480 STMF_SEC2TICK(lport->lport_abort_timeout? 5481 lport->lport_abort_timeout : 5482 ITASK_DEFAULT_ABORT_TIMEOUT))) { 5483 (void) snprintf(info, sizeof (info), 5484 "lport abort timed out"); 5485 stmf_abort_task_offline(itask->itask_task, 0, info); 5486 } 5487 } 5488 } 5489 5490 stmf_status_t 5491 stmf_ctl(int cmd, void *obj, void *arg) 5492 { 5493 stmf_status_t ret; 5494 stmf_i_lu_t *ilu; 5495 stmf_i_local_port_t *ilport; 5496 stmf_state_change_info_t *ssci = (stmf_state_change_info_t *)arg; 5497 5498 mutex_enter(&stmf_state.stmf_lock); 5499 ret = STMF_INVALID_ARG; 5500 if (cmd & STMF_CMD_LU_OP) { 5501 ilu = stmf_lookup_lu((stmf_lu_t *)obj); 5502 if (ilu == NULL) { 5503 goto stmf_ctl_lock_exit; 5504 } 5505 DTRACE_PROBE3(lu__state__change, 5506 stmf_lu_t *, ilu->ilu_lu, 5507 int, cmd, stmf_state_change_info_t *, ssci); 5508 } else if (cmd & STMF_CMD_LPORT_OP) { 5509 ilport = stmf_lookup_lport((stmf_local_port_t *)obj); 5510 if (ilport == NULL) { 5511 goto stmf_ctl_lock_exit; 5512 } 5513 DTRACE_PROBE3(lport__state__change, 5514 stmf_local_port_t *, ilport->ilport_lport, 5515 int, cmd, stmf_state_change_info_t *, ssci); 5516 } else { 5517 goto stmf_ctl_lock_exit; 5518 } 5519 5520 switch (cmd) { 5521 case STMF_CMD_LU_ONLINE: 5522 switch (ilu->ilu_state) { 5523 case STMF_STATE_OFFLINE: 5524 ret = STMF_SUCCESS; 5525 break; 5526 case STMF_STATE_ONLINE: 5527 case STMF_STATE_ONLINING: 5528 ret = STMF_ALREADY; 5529 break; 5530 case STMF_STATE_OFFLINING: 5531 ret = STMF_BUSY; 5532 break; 5533 default: 5534 ret = STMF_BADSTATE; 5535 break; 5536 } 5537 if (ret != STMF_SUCCESS) 5538 goto stmf_ctl_lock_exit; 5539 5540 ilu->ilu_state = STMF_STATE_ONLINING; 5541 mutex_exit(&stmf_state.stmf_lock); 5542 stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg); 5543 break; 5544 5545 case STMF_CMD_LU_ONLINE_COMPLETE: 5546 if (ilu->ilu_state != STMF_STATE_ONLINING) { 5547 ret = STMF_BADSTATE; 5548 goto stmf_ctl_lock_exit; 5549 } 5550 if (((stmf_change_status_t *)arg)->st_completion_status == 5551 STMF_SUCCESS) { 5552 ilu->ilu_state = STMF_STATE_ONLINE; 5553 mutex_exit(&stmf_state.stmf_lock); 5554 ((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj, 5555 STMF_ACK_LU_ONLINE_COMPLETE, arg); 5556 mutex_enter(&stmf_state.stmf_lock); 5557 stmf_add_lu_to_active_sessions((stmf_lu_t *)obj); 5558 } else { 5559 /* XXX: should throw a meesage an record more data */ 5560 ilu->ilu_state = STMF_STATE_OFFLINE; 5561 } 5562 ret = STMF_SUCCESS; 5563 goto stmf_ctl_lock_exit; 5564 5565 case STMF_CMD_LU_OFFLINE: 5566 switch (ilu->ilu_state) { 5567 case STMF_STATE_ONLINE: 5568 ret = STMF_SUCCESS; 5569 break; 5570 case STMF_STATE_OFFLINE: 5571 case STMF_STATE_OFFLINING: 5572 ret = STMF_ALREADY; 5573 break; 5574 case STMF_STATE_ONLINING: 5575 ret = STMF_BUSY; 5576 break; 5577 default: 5578 ret = STMF_BADSTATE; 5579 break; 5580 } 5581 if (ret != STMF_SUCCESS) 5582 goto stmf_ctl_lock_exit; 5583 ilu->ilu_state = STMF_STATE_OFFLINING; 5584 mutex_exit(&stmf_state.stmf_lock); 5585 stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg); 5586 break; 5587 5588 case STMF_CMD_LU_OFFLINE_COMPLETE: 5589 if (ilu->ilu_state != STMF_STATE_OFFLINING) { 5590 ret = STMF_BADSTATE; 5591 goto stmf_ctl_lock_exit; 5592 } 5593 if (((stmf_change_status_t *)arg)->st_completion_status == 5594 STMF_SUCCESS) { 5595 ilu->ilu_state = STMF_STATE_OFFLINE; 5596 mutex_exit(&stmf_state.stmf_lock); 5597 ((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj, 5598 STMF_ACK_LU_OFFLINE_COMPLETE, arg); 5599 mutex_enter(&stmf_state.stmf_lock); 5600 } else { 5601 ilu->ilu_state = STMF_STATE_ONLINE; 5602 stmf_add_lu_to_active_sessions((stmf_lu_t *)obj); 5603 } 5604 mutex_exit(&stmf_state.stmf_lock); 5605 break; 5606 5607 /* 5608 * LPORT_ONLINE/OFFLINE has nothing to do with link offline/online. 5609 * It's related with hardware disable/enable. 5610 */ 5611 case STMF_CMD_LPORT_ONLINE: 5612 switch (ilport->ilport_state) { 5613 case STMF_STATE_OFFLINE: 5614 ret = STMF_SUCCESS; 5615 break; 5616 case STMF_STATE_ONLINE: 5617 case STMF_STATE_ONLINING: 5618 ret = STMF_ALREADY; 5619 break; 5620 case STMF_STATE_OFFLINING: 5621 ret = STMF_BUSY; 5622 break; 5623 default: 5624 ret = STMF_BADSTATE; 5625 break; 5626 } 5627 if (ret != STMF_SUCCESS) 5628 goto stmf_ctl_lock_exit; 5629 5630 /* 5631 * Only user request can recover the port from the 5632 * FORCED_OFFLINE state 5633 */ 5634 if (ilport->ilport_flags & ILPORT_FORCED_OFFLINE) { 5635 if (!(ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) { 5636 ret = STMF_FAILURE; 5637 goto stmf_ctl_lock_exit; 5638 } 5639 } 5640 5641 /* 5642 * Avoid too frequent request to online 5643 */ 5644 if (ssci->st_rflags & STMF_RFLAG_USER_REQUEST) { 5645 ilport->ilport_online_times = 0; 5646 ilport->ilport_avg_interval = 0; 5647 } 5648 if ((ilport->ilport_avg_interval < STMF_AVG_ONLINE_INTERVAL) && 5649 (ilport->ilport_online_times >= 4)) { 5650 ret = STMF_FAILURE; 5651 ilport->ilport_flags |= ILPORT_FORCED_OFFLINE; 5652 stmf_trace(NULL, "stmf_ctl: too frequent request to " 5653 "online the port"); 5654 cmn_err(CE_WARN, "stmf_ctl: too frequent request to " 5655 "online the port, set FORCED_OFFLINE now"); 5656 goto stmf_ctl_lock_exit; 5657 } 5658 if (ilport->ilport_online_times > 0) { 5659 if (ilport->ilport_online_times == 1) { 5660 ilport->ilport_avg_interval = ddi_get_lbolt() - 5661 ilport->ilport_last_online_clock; 5662 } else { 5663 ilport->ilport_avg_interval = 5664 (ilport->ilport_avg_interval + 5665 ddi_get_lbolt() - 5666 ilport->ilport_last_online_clock) >> 1; 5667 } 5668 } 5669 ilport->ilport_last_online_clock = ddi_get_lbolt(); 5670 ilport->ilport_online_times++; 5671 5672 /* 5673 * Submit online service request 5674 */ 5675 ilport->ilport_flags &= ~ILPORT_FORCED_OFFLINE; 5676 ilport->ilport_state = STMF_STATE_ONLINING; 5677 mutex_exit(&stmf_state.stmf_lock); 5678 stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg); 5679 break; 5680 5681 case STMF_CMD_LPORT_ONLINE_COMPLETE: 5682 if (ilport->ilport_state != STMF_STATE_ONLINING) { 5683 ret = STMF_BADSTATE; 5684 goto stmf_ctl_lock_exit; 5685 } 5686 if (((stmf_change_status_t *)arg)->st_completion_status == 5687 STMF_SUCCESS) { 5688 ilport->ilport_state = STMF_STATE_ONLINE; 5689 mutex_exit(&stmf_state.stmf_lock); 5690 ((stmf_local_port_t *)obj)->lport_ctl( 5691 (stmf_local_port_t *)obj, 5692 STMF_ACK_LPORT_ONLINE_COMPLETE, arg); 5693 mutex_enter(&stmf_state.stmf_lock); 5694 } else { 5695 ilport->ilport_state = STMF_STATE_OFFLINE; 5696 } 5697 ret = STMF_SUCCESS; 5698 goto stmf_ctl_lock_exit; 5699 5700 case STMF_CMD_LPORT_OFFLINE: 5701 switch (ilport->ilport_state) { 5702 case STMF_STATE_ONLINE: 5703 ret = STMF_SUCCESS; 5704 break; 5705 case STMF_STATE_OFFLINE: 5706 case STMF_STATE_OFFLINING: 5707 ret = STMF_ALREADY; 5708 break; 5709 case STMF_STATE_ONLINING: 5710 ret = STMF_BUSY; 5711 break; 5712 default: 5713 ret = STMF_BADSTATE; 5714 break; 5715 } 5716 if (ret != STMF_SUCCESS) 5717 goto stmf_ctl_lock_exit; 5718 5719 ilport->ilport_state = STMF_STATE_OFFLINING; 5720 mutex_exit(&stmf_state.stmf_lock); 5721 stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg); 5722 break; 5723 5724 case STMF_CMD_LPORT_OFFLINE_COMPLETE: 5725 if (ilport->ilport_state != STMF_STATE_OFFLINING) { 5726 ret = STMF_BADSTATE; 5727 goto stmf_ctl_lock_exit; 5728 } 5729 if (((stmf_change_status_t *)arg)->st_completion_status == 5730 STMF_SUCCESS) { 5731 ilport->ilport_state = STMF_STATE_OFFLINE; 5732 mutex_exit(&stmf_state.stmf_lock); 5733 ((stmf_local_port_t *)obj)->lport_ctl( 5734 (stmf_local_port_t *)obj, 5735 STMF_ACK_LPORT_OFFLINE_COMPLETE, arg); 5736 mutex_enter(&stmf_state.stmf_lock); 5737 } else { 5738 ilport->ilport_state = STMF_STATE_ONLINE; 5739 } 5740 mutex_exit(&stmf_state.stmf_lock); 5741 break; 5742 5743 default: 5744 cmn_err(CE_WARN, "Invalid ctl cmd received %x", cmd); 5745 ret = STMF_INVALID_ARG; 5746 goto stmf_ctl_lock_exit; 5747 } 5748 5749 return (STMF_SUCCESS); 5750 5751 stmf_ctl_lock_exit:; 5752 mutex_exit(&stmf_state.stmf_lock); 5753 return (ret); 5754 } 5755 5756 /* ARGSUSED */ 5757 stmf_status_t 5758 stmf_info_impl(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf, 5759 uint32_t *bufsizep) 5760 { 5761 return (STMF_NOT_SUPPORTED); 5762 } 5763 5764 /* ARGSUSED */ 5765 stmf_status_t 5766 stmf_info(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf, 5767 uint32_t *bufsizep) 5768 { 5769 uint32_t cl = SI_GET_CLASS(cmd); 5770 5771 if (cl == SI_STMF) { 5772 return (stmf_info_impl(cmd, arg1, arg2, buf, bufsizep)); 5773 } 5774 if (cl == SI_LPORT) { 5775 return (((stmf_local_port_t *)arg1)->lport_info(cmd, arg1, 5776 arg2, buf, bufsizep)); 5777 } else if (cl == SI_LU) { 5778 return (((stmf_lu_t *)arg1)->lu_info(cmd, arg1, arg2, buf, 5779 bufsizep)); 5780 } 5781 5782 return (STMF_NOT_SUPPORTED); 5783 } 5784 5785 /* 5786 * Used by port providers. pwwn is 8 byte wwn, sdid is the devid used by 5787 * stmf to register local ports. The ident should have 20 bytes in buffer 5788 * space to convert the wwn to "wwn.xxxxxxxxxxxxxxxx" string. 5789 */ 5790 void 5791 stmf_wwn_to_devid_desc(scsi_devid_desc_t *sdid, uint8_t *wwn, 5792 uint8_t protocol_id) 5793 { 5794 char wwn_str[20+1]; 5795 5796 sdid->protocol_id = protocol_id; 5797 sdid->piv = 1; 5798 sdid->code_set = CODE_SET_ASCII; 5799 sdid->association = ID_IS_TARGET_PORT; 5800 sdid->ident_length = 20; 5801 /* Convert wwn value to "wwn.XXXXXXXXXXXXXXXX" format */ 5802 (void) snprintf(wwn_str, sizeof (wwn_str), 5803 "wwn.%02X%02X%02X%02X%02X%02X%02X%02X", 5804 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 5805 bcopy(wwn_str, (char *)sdid->ident, 20); 5806 } 5807 5808 5809 stmf_xfer_data_t * 5810 stmf_prepare_tpgs_data(uint8_t ilu_alua) 5811 { 5812 stmf_xfer_data_t *xd; 5813 stmf_i_local_port_t *ilport; 5814 uint8_t *p; 5815 uint32_t sz, asz, nports = 0, nports_standby = 0; 5816 5817 mutex_enter(&stmf_state.stmf_lock); 5818 /* check if any ports are standby and create second group */ 5819 for (ilport = stmf_state.stmf_ilportlist; ilport; 5820 ilport = ilport->ilport_next) { 5821 if (ilport->ilport_standby == 1) { 5822 nports_standby++; 5823 } else { 5824 nports++; 5825 } 5826 } 5827 5828 /* The spec only allows for 255 ports to be reported per group */ 5829 nports = min(nports, 255); 5830 nports_standby = min(nports_standby, 255); 5831 sz = (nports * 4) + 12; 5832 if (nports_standby && ilu_alua) { 5833 sz += (nports_standby * 4) + 8; 5834 } 5835 asz = sz + sizeof (*xd) - 4; 5836 xd = (stmf_xfer_data_t *)kmem_zalloc(asz, KM_NOSLEEP); 5837 if (xd == NULL) { 5838 mutex_exit(&stmf_state.stmf_lock); 5839 return (NULL); 5840 } 5841 xd->alloc_size = asz; 5842 xd->size_left = sz; 5843 5844 p = xd->buf; 5845 5846 *((uint32_t *)p) = BE_32(sz - 4); 5847 p += 4; 5848 p[0] = 0x80; /* PREF */ 5849 p[1] = 5; /* AO_SUP, S_SUP */ 5850 if (stmf_state.stmf_alua_node == 1) { 5851 p[3] = 1; /* Group 1 */ 5852 } else { 5853 p[3] = 0; /* Group 0 */ 5854 } 5855 p[7] = nports & 0xff; 5856 p += 8; 5857 for (ilport = stmf_state.stmf_ilportlist; ilport; 5858 ilport = ilport->ilport_next) { 5859 if (ilport->ilport_standby == 1) { 5860 continue; 5861 } 5862 ((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid); 5863 p += 4; 5864 } 5865 if (nports_standby && ilu_alua) { 5866 p[0] = 0x02; /* Non PREF, Standby */ 5867 p[1] = 5; /* AO_SUP, S_SUP */ 5868 if (stmf_state.stmf_alua_node == 1) { 5869 p[3] = 0; /* Group 0 */ 5870 } else { 5871 p[3] = 1; /* Group 1 */ 5872 } 5873 p[7] = nports_standby & 0xff; 5874 p += 8; 5875 for (ilport = stmf_state.stmf_ilportlist; ilport; 5876 ilport = ilport->ilport_next) { 5877 if (ilport->ilport_standby == 0) { 5878 continue; 5879 } 5880 ((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid); 5881 p += 4; 5882 } 5883 } 5884 5885 mutex_exit(&stmf_state.stmf_lock); 5886 5887 return (xd); 5888 } 5889 5890 struct scsi_devid_desc * 5891 stmf_scsilib_get_devid_desc(uint16_t rtpid) 5892 { 5893 scsi_devid_desc_t *devid = NULL; 5894 stmf_i_local_port_t *ilport; 5895 5896 mutex_enter(&stmf_state.stmf_lock); 5897 5898 for (ilport = stmf_state.stmf_ilportlist; ilport; 5899 ilport = ilport->ilport_next) { 5900 if (ilport->ilport_rtpid == rtpid) { 5901 scsi_devid_desc_t *id = ilport->ilport_lport->lport_id; 5902 uint32_t id_sz = sizeof (scsi_devid_desc_t) - 1 + 5903 id->ident_length; 5904 devid = (scsi_devid_desc_t *)kmem_zalloc(id_sz, 5905 KM_NOSLEEP); 5906 if (devid != NULL) { 5907 bcopy(id, devid, id_sz); 5908 } 5909 break; 5910 } 5911 } 5912 5913 mutex_exit(&stmf_state.stmf_lock); 5914 return (devid); 5915 } 5916 5917 uint16_t 5918 stmf_scsilib_get_lport_rtid(struct scsi_devid_desc *devid) 5919 { 5920 stmf_i_local_port_t *ilport; 5921 scsi_devid_desc_t *id; 5922 uint16_t rtpid = 0; 5923 5924 mutex_enter(&stmf_state.stmf_lock); 5925 for (ilport = stmf_state.stmf_ilportlist; ilport; 5926 ilport = ilport->ilport_next) { 5927 id = ilport->ilport_lport->lport_id; 5928 if ((devid->ident_length == id->ident_length) && 5929 (memcmp(devid->ident, id->ident, id->ident_length) == 0)) { 5930 rtpid = ilport->ilport_rtpid; 5931 break; 5932 } 5933 } 5934 mutex_exit(&stmf_state.stmf_lock); 5935 return (rtpid); 5936 } 5937 5938 static uint16_t stmf_lu_id_gen_number = 0; 5939 5940 stmf_status_t 5941 stmf_scsilib_uniq_lu_id(uint32_t company_id, scsi_devid_desc_t *lu_id) 5942 { 5943 return (stmf_scsilib_uniq_lu_id2(company_id, 0, lu_id)); 5944 } 5945 5946 stmf_status_t 5947 stmf_scsilib_uniq_lu_id2(uint32_t company_id, uint32_t host_id, 5948 scsi_devid_desc_t *lu_id) 5949 { 5950 uint8_t *p; 5951 struct timeval32 timestamp32; 5952 uint32_t *t = (uint32_t *)×tamp32; 5953 struct ether_addr mac; 5954 uint8_t *e = (uint8_t *)&mac; 5955 int hid = (int)host_id; 5956 5957 if (company_id == COMPANY_ID_NONE) 5958 company_id = COMPANY_ID_SUN; 5959 5960 if (lu_id->ident_length != 0x10) 5961 return (STMF_INVALID_ARG); 5962 5963 p = (uint8_t *)lu_id; 5964 5965 atomic_add_16(&stmf_lu_id_gen_number, 1); 5966 5967 p[0] = 0xf1; p[1] = 3; p[2] = 0; p[3] = 0x10; 5968 p[4] = ((company_id >> 20) & 0xf) | 0x60; 5969 p[5] = (company_id >> 12) & 0xff; 5970 p[6] = (company_id >> 4) & 0xff; 5971 p[7] = (company_id << 4) & 0xf0; 5972 if (hid == 0 && !localetheraddr((struct ether_addr *)NULL, &mac)) { 5973 hid = BE_32((int)zone_get_hostid(NULL)); 5974 } 5975 if (hid != 0) { 5976 e[0] = (hid >> 24) & 0xff; 5977 e[1] = (hid >> 16) & 0xff; 5978 e[2] = (hid >> 8) & 0xff; 5979 e[3] = hid & 0xff; 5980 e[4] = e[5] = 0; 5981 } 5982 bcopy(e, p+8, 6); 5983 uniqtime32(×tamp32); 5984 *t = BE_32(*t); 5985 bcopy(t, p+14, 4); 5986 p[18] = (stmf_lu_id_gen_number >> 8) & 0xff; 5987 p[19] = stmf_lu_id_gen_number & 0xff; 5988 5989 return (STMF_SUCCESS); 5990 } 5991 5992 /* 5993 * saa is sense key, ASC, ASCQ 5994 */ 5995 void 5996 stmf_scsilib_send_status(scsi_task_t *task, uint8_t st, uint32_t saa) 5997 { 5998 uint8_t sd[18]; 5999 task->task_scsi_status = st; 6000 if (st == 2) { 6001 bzero(sd, 18); 6002 sd[0] = 0x70; 6003 sd[2] = (saa >> 16) & 0xf; 6004 sd[7] = 10; 6005 sd[12] = (saa >> 8) & 0xff; 6006 sd[13] = saa & 0xff; 6007 task->task_sense_data = sd; 6008 task->task_sense_length = 18; 6009 } else { 6010 task->task_sense_data = NULL; 6011 task->task_sense_length = 0; 6012 } 6013 (void) stmf_send_scsi_status(task, STMF_IOF_LU_DONE); 6014 } 6015 6016 uint32_t 6017 stmf_scsilib_prepare_vpd_page83(scsi_task_t *task, uint8_t *page, 6018 uint32_t page_len, uint8_t byte0, uint32_t vpd_mask) 6019 { 6020 uint8_t *p = NULL; 6021 uint8_t small_buf[32]; 6022 uint32_t sz = 0; 6023 uint32_t n = 4; 6024 uint32_t m = 0; 6025 uint32_t last_bit = 0; 6026 6027 if (page_len < 4) 6028 return (0); 6029 if (page_len > 65535) 6030 page_len = 65535; 6031 6032 page[0] = byte0; 6033 page[1] = 0x83; 6034 6035 /* CONSTCOND */ 6036 while (1) { 6037 m += sz; 6038 if (sz && (page_len > n)) { 6039 uint32_t copysz; 6040 copysz = page_len > (n + sz) ? sz : page_len - n; 6041 bcopy(p, page + n, copysz); 6042 n += copysz; 6043 } 6044 vpd_mask &= ~last_bit; 6045 if (vpd_mask == 0) 6046 break; 6047 6048 if (vpd_mask & STMF_VPD_LU_ID) { 6049 last_bit = STMF_VPD_LU_ID; 6050 sz = task->task_lu->lu_id->ident_length + 4; 6051 p = (uint8_t *)task->task_lu->lu_id; 6052 continue; 6053 } else if (vpd_mask & STMF_VPD_TARGET_ID) { 6054 last_bit = STMF_VPD_TARGET_ID; 6055 sz = task->task_lport->lport_id->ident_length + 4; 6056 p = (uint8_t *)task->task_lport->lport_id; 6057 continue; 6058 } else if (vpd_mask & STMF_VPD_TP_GROUP) { 6059 stmf_i_local_port_t *ilport; 6060 last_bit = STMF_VPD_TP_GROUP; 6061 p = small_buf; 6062 bzero(p, 8); 6063 p[0] = 1; 6064 p[1] = 0x15; 6065 p[3] = 4; 6066 ilport = (stmf_i_local_port_t *) 6067 task->task_lport->lport_stmf_private; 6068 /* 6069 * If we're in alua mode, group 1 contains all alua 6070 * participating ports and all standby ports 6071 * > 255. Otherwise, if we're in alua mode, any local 6072 * ports (non standby/pppt) are also in group 1 if the 6073 * alua node is 1. Otherwise the group is 0. 6074 */ 6075 if ((stmf_state.stmf_alua_state && 6076 (ilport->ilport_alua || ilport->ilport_standby) && 6077 ilport->ilport_rtpid > 255) || 6078 (stmf_state.stmf_alua_node == 1 && 6079 ilport->ilport_standby != 1)) { 6080 p[7] = 1; /* Group 1 */ 6081 } 6082 sz = 8; 6083 continue; 6084 } else if (vpd_mask & STMF_VPD_RELATIVE_TP_ID) { 6085 stmf_i_local_port_t *ilport; 6086 6087 last_bit = STMF_VPD_RELATIVE_TP_ID; 6088 p = small_buf; 6089 bzero(p, 8); 6090 p[0] = 1; 6091 p[1] = 0x14; 6092 p[3] = 4; 6093 ilport = (stmf_i_local_port_t *) 6094 task->task_lport->lport_stmf_private; 6095 p[6] = (ilport->ilport_rtpid >> 8) & 0xff; 6096 p[7] = ilport->ilport_rtpid & 0xff; 6097 sz = 8; 6098 continue; 6099 } else { 6100 cmn_err(CE_WARN, "Invalid vpd_mask"); 6101 break; 6102 } 6103 } 6104 6105 page[2] = (m >> 8) & 0xff; 6106 page[3] = m & 0xff; 6107 6108 return (n); 6109 } 6110 6111 void 6112 stmf_scsilib_handle_report_tpgs(scsi_task_t *task, stmf_data_buf_t *dbuf) 6113 { 6114 stmf_i_scsi_task_t *itask = 6115 (stmf_i_scsi_task_t *)task->task_stmf_private; 6116 stmf_i_lu_t *ilu = 6117 (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 6118 stmf_xfer_data_t *xd; 6119 uint32_t sz, minsz; 6120 6121 itask->itask_flags |= ITASK_DEFAULT_HANDLING; 6122 task->task_cmd_xfer_length = 6123 ((((uint32_t)task->task_cdb[6]) << 24) | 6124 (((uint32_t)task->task_cdb[7]) << 16) | 6125 (((uint32_t)task->task_cdb[8]) << 8) | 6126 ((uint32_t)task->task_cdb[9])); 6127 6128 if (task->task_additional_flags & 6129 TASK_AF_NO_EXPECTED_XFER_LENGTH) { 6130 task->task_expected_xfer_length = 6131 task->task_cmd_xfer_length; 6132 } 6133 6134 if (task->task_cmd_xfer_length == 0) { 6135 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 6136 return; 6137 } 6138 if (task->task_cmd_xfer_length < 4) { 6139 stmf_scsilib_send_status(task, STATUS_CHECK, 6140 STMF_SAA_INVALID_FIELD_IN_CDB); 6141 return; 6142 } 6143 6144 sz = min(task->task_expected_xfer_length, 6145 task->task_cmd_xfer_length); 6146 6147 xd = stmf_prepare_tpgs_data(ilu->ilu_alua); 6148 6149 if (xd == NULL) { 6150 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6151 STMF_ALLOC_FAILURE, NULL); 6152 return; 6153 } 6154 6155 sz = min(sz, xd->size_left); 6156 xd->size_left = sz; 6157 minsz = min(512, sz); 6158 6159 if (dbuf == NULL) 6160 dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0); 6161 if (dbuf == NULL) { 6162 kmem_free(xd, xd->alloc_size); 6163 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6164 STMF_ALLOC_FAILURE, NULL); 6165 return; 6166 } 6167 dbuf->db_lu_private = xd; 6168 stmf_xd_to_dbuf(dbuf, 1); 6169 6170 dbuf->db_flags = DB_DIRECTION_TO_RPORT; 6171 (void) stmf_xfer_data(task, dbuf, 0); 6172 6173 } 6174 6175 void 6176 stmf_scsilib_handle_task_mgmt(scsi_task_t *task) 6177 { 6178 6179 switch (task->task_mgmt_function) { 6180 /* 6181 * For now we will abort all I/Os on the LU in case of ABORT_TASK_SET 6182 * and ABORT_TASK. But unlike LUN_RESET we will not reset LU state 6183 * in these cases. This needs to be changed to abort only the required 6184 * set. 6185 */ 6186 case TM_ABORT_TASK: 6187 case TM_ABORT_TASK_SET: 6188 case TM_CLEAR_TASK_SET: 6189 case TM_LUN_RESET: 6190 stmf_handle_lun_reset(task); 6191 /* issue the reset to the proxy node as well */ 6192 if (stmf_state.stmf_alua_state == 1) { 6193 (void) stmf_proxy_scsi_cmd(task, NULL); 6194 } 6195 return; 6196 case TM_TARGET_RESET: 6197 case TM_TARGET_COLD_RESET: 6198 case TM_TARGET_WARM_RESET: 6199 stmf_handle_target_reset(task); 6200 return; 6201 default: 6202 /* We dont support this task mgmt function */ 6203 stmf_scsilib_send_status(task, STATUS_CHECK, 6204 STMF_SAA_INVALID_FIELD_IN_CMD_IU); 6205 return; 6206 } 6207 } 6208 6209 void 6210 stmf_handle_lun_reset(scsi_task_t *task) 6211 { 6212 stmf_i_scsi_task_t *itask; 6213 stmf_i_lu_t *ilu; 6214 6215 itask = (stmf_i_scsi_task_t *)task->task_stmf_private; 6216 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 6217 6218 /* 6219 * To sync with target reset, grab this lock. The LU is not going 6220 * anywhere as there is atleast one task pending (this task). 6221 */ 6222 mutex_enter(&stmf_state.stmf_lock); 6223 6224 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 6225 mutex_exit(&stmf_state.stmf_lock); 6226 stmf_scsilib_send_status(task, STATUS_CHECK, 6227 STMF_SAA_OPERATION_IN_PROGRESS); 6228 return; 6229 } 6230 atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE); 6231 mutex_exit(&stmf_state.stmf_lock); 6232 6233 /* 6234 * Mark this task as the one causing LU reset so that we know who 6235 * was responsible for setting the ILU_RESET_ACTIVE. In case this 6236 * task itself gets aborted, we will clear ILU_RESET_ACTIVE. 6237 */ 6238 itask->itask_flags |= ITASK_DEFAULT_HANDLING | ITASK_CAUSING_LU_RESET; 6239 6240 /* Initiatiate abort on all commands on this LU except this one */ 6241 stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED, task->task_lu); 6242 6243 /* Start polling on this task */ 6244 if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT) 6245 != STMF_SUCCESS) { 6246 stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE, 6247 NULL); 6248 return; 6249 } 6250 } 6251 6252 void 6253 stmf_handle_target_reset(scsi_task_t *task) 6254 { 6255 stmf_i_scsi_task_t *itask; 6256 stmf_i_lu_t *ilu; 6257 stmf_i_scsi_session_t *iss; 6258 stmf_lun_map_t *lm; 6259 stmf_lun_map_ent_t *lm_ent; 6260 int i, lf; 6261 6262 itask = (stmf_i_scsi_task_t *)task->task_stmf_private; 6263 iss = (stmf_i_scsi_session_t *)task->task_session->ss_stmf_private; 6264 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 6265 6266 /* 6267 * To sync with LUN reset, grab this lock. The session is not going 6268 * anywhere as there is atleast one task pending (this task). 6269 */ 6270 mutex_enter(&stmf_state.stmf_lock); 6271 6272 /* Grab the session lock as a writer to prevent any changes in it */ 6273 rw_enter(iss->iss_lockp, RW_WRITER); 6274 6275 if (iss->iss_flags & ISS_RESET_ACTIVE) { 6276 rw_exit(iss->iss_lockp); 6277 mutex_exit(&stmf_state.stmf_lock); 6278 stmf_scsilib_send_status(task, STATUS_CHECK, 6279 STMF_SAA_OPERATION_IN_PROGRESS); 6280 return; 6281 } 6282 atomic_or_32(&iss->iss_flags, ISS_RESET_ACTIVE); 6283 6284 /* 6285 * Now go through each LUN in this session and make sure all of them 6286 * can be reset. 6287 */ 6288 lm = iss->iss_sm; 6289 for (i = 0, lf = 0; i < lm->lm_nentries; i++) { 6290 if (lm->lm_plus[i] == NULL) 6291 continue; 6292 lf++; 6293 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 6294 ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private); 6295 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 6296 atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE); 6297 rw_exit(iss->iss_lockp); 6298 mutex_exit(&stmf_state.stmf_lock); 6299 stmf_scsilib_send_status(task, STATUS_CHECK, 6300 STMF_SAA_OPERATION_IN_PROGRESS); 6301 return; 6302 } 6303 } 6304 if (lf == 0) { 6305 /* No luns in this session */ 6306 atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE); 6307 rw_exit(iss->iss_lockp); 6308 mutex_exit(&stmf_state.stmf_lock); 6309 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 6310 return; 6311 } 6312 6313 /* ok, start the damage */ 6314 itask->itask_flags |= ITASK_DEFAULT_HANDLING | 6315 ITASK_CAUSING_TARGET_RESET; 6316 for (i = 0; i < lm->lm_nentries; i++) { 6317 if (lm->lm_plus[i] == NULL) 6318 continue; 6319 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 6320 ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private); 6321 atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE); 6322 } 6323 6324 for (i = 0; i < lm->lm_nentries; i++) { 6325 if (lm->lm_plus[i] == NULL) 6326 continue; 6327 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 6328 stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED, 6329 lm_ent->ent_lu); 6330 } 6331 6332 rw_exit(iss->iss_lockp); 6333 mutex_exit(&stmf_state.stmf_lock); 6334 6335 /* Start polling on this task */ 6336 if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT) 6337 != STMF_SUCCESS) { 6338 stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE, 6339 NULL); 6340 return; 6341 } 6342 } 6343 6344 int 6345 stmf_handle_cmd_during_ic(stmf_i_scsi_task_t *itask) 6346 { 6347 scsi_task_t *task = itask->itask_task; 6348 stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *) 6349 task->task_session->ss_stmf_private; 6350 6351 rw_enter(iss->iss_lockp, RW_WRITER); 6352 if (((iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) == 0) || 6353 (task->task_cdb[0] == SCMD_INQUIRY)) { 6354 rw_exit(iss->iss_lockp); 6355 return (0); 6356 } 6357 atomic_and_32(&iss->iss_flags, 6358 ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS)); 6359 rw_exit(iss->iss_lockp); 6360 6361 if (task->task_cdb[0] == SCMD_REPORT_LUNS) { 6362 return (0); 6363 } 6364 stmf_scsilib_send_status(task, STATUS_CHECK, 6365 STMF_SAA_REPORT_LUN_DATA_HAS_CHANGED); 6366 return (1); 6367 } 6368 6369 void 6370 stmf_worker_init() 6371 { 6372 uint32_t i; 6373 6374 /* Make local copy of global tunables */ 6375 stmf_i_max_nworkers = stmf_max_nworkers; 6376 stmf_i_min_nworkers = stmf_min_nworkers; 6377 6378 ASSERT(stmf_workers == NULL); 6379 if (stmf_i_min_nworkers < 4) { 6380 stmf_i_min_nworkers = 4; 6381 } 6382 if (stmf_i_max_nworkers < stmf_i_min_nworkers) { 6383 stmf_i_max_nworkers = stmf_i_min_nworkers; 6384 } 6385 stmf_workers = (stmf_worker_t *)kmem_zalloc( 6386 sizeof (stmf_worker_t) * stmf_i_max_nworkers, KM_SLEEP); 6387 for (i = 0; i < stmf_i_max_nworkers; i++) { 6388 stmf_worker_t *w = &stmf_workers[i]; 6389 mutex_init(&w->worker_lock, NULL, MUTEX_DRIVER, NULL); 6390 cv_init(&w->worker_cv, NULL, CV_DRIVER, NULL); 6391 } 6392 stmf_worker_mgmt_delay = drv_usectohz(20 * 1000); 6393 stmf_workers_state = STMF_WORKERS_ENABLED; 6394 6395 /* Workers will be started by stmf_worker_mgmt() */ 6396 6397 /* Lets wait for atleast one worker to start */ 6398 while (stmf_nworkers_cur == 0) 6399 delay(drv_usectohz(20 * 1000)); 6400 stmf_worker_mgmt_delay = drv_usectohz(3 * 1000 * 1000); 6401 } 6402 6403 stmf_status_t 6404 stmf_worker_fini() 6405 { 6406 int i; 6407 clock_t sb; 6408 6409 if (stmf_workers_state == STMF_WORKERS_DISABLED) 6410 return (STMF_SUCCESS); 6411 ASSERT(stmf_workers); 6412 stmf_workers_state = STMF_WORKERS_DISABLED; 6413 stmf_worker_mgmt_delay = drv_usectohz(20 * 1000); 6414 cv_signal(&stmf_state.stmf_cv); 6415 6416 sb = ddi_get_lbolt() + drv_usectohz(10 * 1000 * 1000); 6417 /* Wait for all the threads to die */ 6418 while (stmf_nworkers_cur != 0) { 6419 if (ddi_get_lbolt() > sb) { 6420 stmf_workers_state = STMF_WORKERS_ENABLED; 6421 return (STMF_BUSY); 6422 } 6423 delay(drv_usectohz(100 * 1000)); 6424 } 6425 for (i = 0; i < stmf_i_max_nworkers; i++) { 6426 stmf_worker_t *w = &stmf_workers[i]; 6427 mutex_destroy(&w->worker_lock); 6428 cv_destroy(&w->worker_cv); 6429 } 6430 kmem_free(stmf_workers, sizeof (stmf_worker_t) * stmf_i_max_nworkers); 6431 stmf_workers = NULL; 6432 6433 return (STMF_SUCCESS); 6434 } 6435 6436 void 6437 stmf_worker_task(void *arg) 6438 { 6439 stmf_worker_t *w; 6440 stmf_i_scsi_session_t *iss; 6441 scsi_task_t *task; 6442 stmf_i_scsi_task_t *itask; 6443 stmf_data_buf_t *dbuf; 6444 stmf_lu_t *lu; 6445 clock_t wait_timer = 0; 6446 clock_t wait_ticks, wait_delta = 0; 6447 uint32_t old, new; 6448 uint8_t curcmd; 6449 uint8_t abort_free; 6450 uint8_t wait_queue; 6451 uint8_t dec_qdepth; 6452 6453 w = (stmf_worker_t *)arg; 6454 wait_ticks = drv_usectohz(10000); 6455 6456 DTRACE_PROBE1(worker__create, stmf_worker_t, w); 6457 mutex_enter(&w->worker_lock); 6458 w->worker_flags |= STMF_WORKER_STARTED | STMF_WORKER_ACTIVE; 6459 stmf_worker_loop:; 6460 if ((w->worker_ref_count == 0) && 6461 (w->worker_flags & STMF_WORKER_TERMINATE)) { 6462 w->worker_flags &= ~(STMF_WORKER_STARTED | 6463 STMF_WORKER_ACTIVE | STMF_WORKER_TERMINATE); 6464 w->worker_tid = NULL; 6465 mutex_exit(&w->worker_lock); 6466 DTRACE_PROBE1(worker__destroy, stmf_worker_t, w); 6467 thread_exit(); 6468 } 6469 /* CONSTCOND */ 6470 while (1) { 6471 dec_qdepth = 0; 6472 if (wait_timer && (ddi_get_lbolt() >= wait_timer)) { 6473 wait_timer = 0; 6474 wait_delta = 0; 6475 if (w->worker_wait_head) { 6476 ASSERT(w->worker_wait_tail); 6477 if (w->worker_task_head == NULL) 6478 w->worker_task_head = 6479 w->worker_wait_head; 6480 else 6481 w->worker_task_tail->itask_worker_next = 6482 w->worker_wait_head; 6483 w->worker_task_tail = w->worker_wait_tail; 6484 w->worker_wait_head = w->worker_wait_tail = 6485 NULL; 6486 } 6487 } 6488 if ((itask = w->worker_task_head) == NULL) { 6489 break; 6490 } 6491 task = itask->itask_task; 6492 DTRACE_PROBE2(worker__active, stmf_worker_t, w, 6493 scsi_task_t *, task); 6494 w->worker_task_head = itask->itask_worker_next; 6495 if (w->worker_task_head == NULL) 6496 w->worker_task_tail = NULL; 6497 6498 wait_queue = 0; 6499 abort_free = 0; 6500 if (itask->itask_ncmds > 0) { 6501 curcmd = itask->itask_cmd_stack[itask->itask_ncmds - 1]; 6502 } else { 6503 ASSERT(itask->itask_flags & ITASK_BEING_ABORTED); 6504 } 6505 do { 6506 old = itask->itask_flags; 6507 if (old & ITASK_BEING_ABORTED) { 6508 itask->itask_ncmds = 1; 6509 curcmd = itask->itask_cmd_stack[0] = 6510 ITASK_CMD_ABORT; 6511 goto out_itask_flag_loop; 6512 } else if ((curcmd & ITASK_CMD_MASK) == 6513 ITASK_CMD_NEW_TASK) { 6514 /* 6515 * set ITASK_KSTAT_IN_RUNQ, this flag 6516 * will not reset until task completed 6517 */ 6518 new = old | ITASK_KNOWN_TO_LU | 6519 ITASK_KSTAT_IN_RUNQ; 6520 } else { 6521 goto out_itask_flag_loop; 6522 } 6523 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 6524 6525 out_itask_flag_loop: 6526 6527 /* 6528 * Decide if this task needs to go to a queue and/or if 6529 * we can decrement the itask_cmd_stack. 6530 */ 6531 if (curcmd == ITASK_CMD_ABORT) { 6532 if (itask->itask_flags & (ITASK_KNOWN_TO_LU | 6533 ITASK_KNOWN_TO_TGT_PORT)) { 6534 wait_queue = 1; 6535 } else { 6536 abort_free = 1; 6537 } 6538 } else if ((curcmd & ITASK_CMD_POLL) && 6539 (itask->itask_poll_timeout > ddi_get_lbolt())) { 6540 wait_queue = 1; 6541 } 6542 6543 if (wait_queue) { 6544 itask->itask_worker_next = NULL; 6545 if (w->worker_wait_tail) { 6546 w->worker_wait_tail->itask_worker_next = itask; 6547 } else { 6548 w->worker_wait_head = itask; 6549 } 6550 w->worker_wait_tail = itask; 6551 if (wait_timer == 0) { 6552 wait_timer = ddi_get_lbolt() + wait_ticks; 6553 wait_delta = wait_ticks; 6554 } 6555 } else if ((--(itask->itask_ncmds)) != 0) { 6556 itask->itask_worker_next = NULL; 6557 if (w->worker_task_tail) { 6558 w->worker_task_tail->itask_worker_next = itask; 6559 } else { 6560 w->worker_task_head = itask; 6561 } 6562 w->worker_task_tail = itask; 6563 } else { 6564 atomic_and_32(&itask->itask_flags, 6565 ~ITASK_IN_WORKER_QUEUE); 6566 /* 6567 * This is where the queue depth should go down by 6568 * one but we delay that on purpose to account for 6569 * the call into the provider. The actual decrement 6570 * happens after the worker has done its job. 6571 */ 6572 dec_qdepth = 1; 6573 itask->itask_waitq_time += 6574 gethrtime() - itask->itask_waitq_enter_timestamp; 6575 } 6576 6577 /* We made it here means we are going to call LU */ 6578 if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0) 6579 lu = task->task_lu; 6580 else 6581 lu = dlun0; 6582 dbuf = itask->itask_dbufs[ITASK_CMD_BUF_NDX(curcmd)]; 6583 mutex_exit(&w->worker_lock); 6584 curcmd &= ITASK_CMD_MASK; 6585 switch (curcmd) { 6586 case ITASK_CMD_NEW_TASK: 6587 iss = (stmf_i_scsi_session_t *) 6588 task->task_session->ss_stmf_private; 6589 stmf_itl_lu_new_task(itask); 6590 if (iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) { 6591 if (stmf_handle_cmd_during_ic(itask)) 6592 break; 6593 } 6594 #ifdef DEBUG 6595 if (stmf_drop_task_counter > 0) { 6596 if (atomic_add_32_nv( 6597 (uint32_t *)&stmf_drop_task_counter, 6598 -1) == 1) { 6599 break; 6600 } 6601 } 6602 #endif 6603 DTRACE_PROBE1(scsi__task__start, scsi_task_t *, task); 6604 lu->lu_new_task(task, dbuf); 6605 break; 6606 case ITASK_CMD_DATA_XFER_DONE: 6607 lu->lu_dbuf_xfer_done(task, dbuf); 6608 break; 6609 case ITASK_CMD_STATUS_DONE: 6610 lu->lu_send_status_done(task); 6611 break; 6612 case ITASK_CMD_ABORT: 6613 if (abort_free) { 6614 stmf_task_free(task); 6615 } else { 6616 stmf_do_task_abort(task); 6617 } 6618 break; 6619 case ITASK_CMD_POLL_LU: 6620 if (!wait_queue) { 6621 lu->lu_task_poll(task); 6622 } 6623 break; 6624 case ITASK_CMD_POLL_LPORT: 6625 if (!wait_queue) 6626 task->task_lport->lport_task_poll(task); 6627 break; 6628 case ITASK_CMD_SEND_STATUS: 6629 /* case ITASK_CMD_XFER_DATA: */ 6630 break; 6631 } 6632 mutex_enter(&w->worker_lock); 6633 if (dec_qdepth) { 6634 w->worker_queue_depth--; 6635 } 6636 } 6637 if ((w->worker_flags & STMF_WORKER_TERMINATE) && (wait_timer == 0)) { 6638 if (w->worker_ref_count == 0) 6639 goto stmf_worker_loop; 6640 else { 6641 wait_timer = ddi_get_lbolt() + 1; 6642 wait_delta = 1; 6643 } 6644 } 6645 w->worker_flags &= ~STMF_WORKER_ACTIVE; 6646 if (wait_timer) { 6647 DTRACE_PROBE1(worker__timed__sleep, stmf_worker_t, w); 6648 (void) cv_reltimedwait(&w->worker_cv, &w->worker_lock, 6649 wait_delta, TR_CLOCK_TICK); 6650 } else { 6651 DTRACE_PROBE1(worker__sleep, stmf_worker_t, w); 6652 cv_wait(&w->worker_cv, &w->worker_lock); 6653 } 6654 DTRACE_PROBE1(worker__wakeup, stmf_worker_t, w); 6655 w->worker_flags |= STMF_WORKER_ACTIVE; 6656 goto stmf_worker_loop; 6657 } 6658 6659 void 6660 stmf_worker_mgmt() 6661 { 6662 int i; 6663 int workers_needed; 6664 uint32_t qd; 6665 clock_t tps, d = 0; 6666 uint32_t cur_max_ntasks = 0; 6667 stmf_worker_t *w; 6668 6669 /* Check if we are trying to increase the # of threads */ 6670 for (i = stmf_nworkers_cur; i < stmf_nworkers_needed; i++) { 6671 if (stmf_workers[i].worker_flags & STMF_WORKER_STARTED) { 6672 stmf_nworkers_cur++; 6673 stmf_nworkers_accepting_cmds++; 6674 } else { 6675 /* Wait for transition to complete */ 6676 return; 6677 } 6678 } 6679 /* Check if we are trying to decrease the # of workers */ 6680 for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) { 6681 if ((stmf_workers[i].worker_flags & STMF_WORKER_STARTED) == 0) { 6682 stmf_nworkers_cur--; 6683 /* 6684 * stmf_nworkers_accepting_cmds has already been 6685 * updated by the request to reduce the # of workers. 6686 */ 6687 } else { 6688 /* Wait for transition to complete */ 6689 return; 6690 } 6691 } 6692 /* Check if we are being asked to quit */ 6693 if (stmf_workers_state != STMF_WORKERS_ENABLED) { 6694 if (stmf_nworkers_cur) { 6695 workers_needed = 0; 6696 goto worker_mgmt_trigger_change; 6697 } 6698 return; 6699 } 6700 /* Check if we are starting */ 6701 if (stmf_nworkers_cur < stmf_i_min_nworkers) { 6702 workers_needed = stmf_i_min_nworkers; 6703 goto worker_mgmt_trigger_change; 6704 } 6705 6706 tps = drv_usectohz(1 * 1000 * 1000); 6707 if ((stmf_wm_last != 0) && 6708 ((d = ddi_get_lbolt() - stmf_wm_last) > tps)) { 6709 qd = 0; 6710 for (i = 0; i < stmf_nworkers_accepting_cmds; i++) { 6711 qd += stmf_workers[i].worker_max_qdepth_pu; 6712 stmf_workers[i].worker_max_qdepth_pu = 0; 6713 if (stmf_workers[i].worker_max_sys_qdepth_pu > 6714 cur_max_ntasks) { 6715 cur_max_ntasks = 6716 stmf_workers[i].worker_max_sys_qdepth_pu; 6717 } 6718 stmf_workers[i].worker_max_sys_qdepth_pu = 0; 6719 } 6720 } 6721 stmf_wm_last = ddi_get_lbolt(); 6722 if (d <= tps) { 6723 /* still ramping up */ 6724 return; 6725 } 6726 /* max qdepth cannot be more than max tasks */ 6727 if (qd > cur_max_ntasks) 6728 qd = cur_max_ntasks; 6729 6730 /* See if we have more workers */ 6731 if (qd < stmf_nworkers_accepting_cmds) { 6732 /* 6733 * Since we dont reduce the worker count right away, monitor 6734 * the highest load during the scale_down_delay. 6735 */ 6736 if (qd > stmf_worker_scale_down_qd) 6737 stmf_worker_scale_down_qd = qd; 6738 if (stmf_worker_scale_down_timer == 0) { 6739 stmf_worker_scale_down_timer = ddi_get_lbolt() + 6740 drv_usectohz(stmf_worker_scale_down_delay * 6741 1000 * 1000); 6742 return; 6743 } 6744 if (ddi_get_lbolt() < stmf_worker_scale_down_timer) { 6745 return; 6746 } 6747 /* Its time to reduce the workers */ 6748 if (stmf_worker_scale_down_qd < stmf_i_min_nworkers) 6749 stmf_worker_scale_down_qd = stmf_i_min_nworkers; 6750 if (stmf_worker_scale_down_qd > stmf_i_max_nworkers) 6751 stmf_worker_scale_down_qd = stmf_i_max_nworkers; 6752 if (stmf_worker_scale_down_qd == stmf_nworkers_cur) 6753 return; 6754 workers_needed = stmf_worker_scale_down_qd; 6755 stmf_worker_scale_down_qd = 0; 6756 goto worker_mgmt_trigger_change; 6757 } 6758 stmf_worker_scale_down_qd = 0; 6759 stmf_worker_scale_down_timer = 0; 6760 if (qd > stmf_i_max_nworkers) 6761 qd = stmf_i_max_nworkers; 6762 if (qd < stmf_i_min_nworkers) 6763 qd = stmf_i_min_nworkers; 6764 if (qd == stmf_nworkers_cur) 6765 return; 6766 workers_needed = qd; 6767 goto worker_mgmt_trigger_change; 6768 6769 /* NOTREACHED */ 6770 return; 6771 6772 worker_mgmt_trigger_change: 6773 ASSERT(workers_needed != stmf_nworkers_cur); 6774 if (workers_needed > stmf_nworkers_cur) { 6775 stmf_nworkers_needed = workers_needed; 6776 for (i = stmf_nworkers_cur; i < workers_needed; i++) { 6777 w = &stmf_workers[i]; 6778 w->worker_tid = thread_create(NULL, 0, stmf_worker_task, 6779 (void *)&stmf_workers[i], 0, &p0, TS_RUN, 6780 minclsyspri); 6781 } 6782 return; 6783 } 6784 /* At this point we know that we are decreasing the # of workers */ 6785 stmf_nworkers_accepting_cmds = workers_needed; 6786 stmf_nworkers_needed = workers_needed; 6787 /* Signal the workers that its time to quit */ 6788 for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) { 6789 w = &stmf_workers[i]; 6790 ASSERT(w && (w->worker_flags & STMF_WORKER_STARTED)); 6791 mutex_enter(&w->worker_lock); 6792 w->worker_flags |= STMF_WORKER_TERMINATE; 6793 if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) 6794 cv_signal(&w->worker_cv); 6795 mutex_exit(&w->worker_lock); 6796 } 6797 } 6798 6799 /* 6800 * Fills out a dbuf from stmf_xfer_data_t (contained in the db_lu_private). 6801 * If all the data has been filled out, frees the xd and makes 6802 * db_lu_private NULL. 6803 */ 6804 void 6805 stmf_xd_to_dbuf(stmf_data_buf_t *dbuf, int set_rel_off) 6806 { 6807 stmf_xfer_data_t *xd; 6808 uint8_t *p; 6809 int i; 6810 uint32_t s; 6811 6812 xd = (stmf_xfer_data_t *)dbuf->db_lu_private; 6813 dbuf->db_data_size = 0; 6814 if (set_rel_off) 6815 dbuf->db_relative_offset = xd->size_done; 6816 for (i = 0; i < dbuf->db_sglist_length; i++) { 6817 s = min(xd->size_left, dbuf->db_sglist[i].seg_length); 6818 p = &xd->buf[xd->size_done]; 6819 bcopy(p, dbuf->db_sglist[i].seg_addr, s); 6820 xd->size_left -= s; 6821 xd->size_done += s; 6822 dbuf->db_data_size += s; 6823 if (xd->size_left == 0) { 6824 kmem_free(xd, xd->alloc_size); 6825 dbuf->db_lu_private = NULL; 6826 return; 6827 } 6828 } 6829 } 6830 6831 /* ARGSUSED */ 6832 stmf_status_t 6833 stmf_dlun0_task_alloc(scsi_task_t *task) 6834 { 6835 return (STMF_SUCCESS); 6836 } 6837 6838 void 6839 stmf_dlun0_new_task(scsi_task_t *task, stmf_data_buf_t *dbuf) 6840 { 6841 uint8_t *cdbp = (uint8_t *)&task->task_cdb[0]; 6842 stmf_i_scsi_session_t *iss; 6843 uint32_t sz, minsz; 6844 uint8_t *p; 6845 stmf_xfer_data_t *xd; 6846 uint8_t inq_page_length = 31; 6847 6848 if (task->task_mgmt_function) { 6849 stmf_scsilib_handle_task_mgmt(task); 6850 return; 6851 } 6852 6853 switch (cdbp[0]) { 6854 case SCMD_INQUIRY: 6855 /* 6856 * Basic protocol checks. In addition, only reply to 6857 * standard inquiry. Otherwise, the LU provider needs 6858 * to respond. 6859 */ 6860 6861 if (cdbp[2] || (cdbp[1] & 1) || cdbp[5]) { 6862 stmf_scsilib_send_status(task, STATUS_CHECK, 6863 STMF_SAA_INVALID_FIELD_IN_CDB); 6864 return; 6865 } 6866 6867 task->task_cmd_xfer_length = 6868 (((uint32_t)cdbp[3]) << 8) | cdbp[4]; 6869 6870 if (task->task_additional_flags & 6871 TASK_AF_NO_EXPECTED_XFER_LENGTH) { 6872 task->task_expected_xfer_length = 6873 task->task_cmd_xfer_length; 6874 } 6875 6876 sz = min(task->task_expected_xfer_length, 6877 min(36, task->task_cmd_xfer_length)); 6878 minsz = 36; 6879 6880 if (sz == 0) { 6881 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 6882 return; 6883 } 6884 6885 if (dbuf && (dbuf->db_sglist[0].seg_length < 36)) { 6886 /* 6887 * Ignore any preallocated dbuf if the size is less 6888 * than 36. It will be freed during the task_free. 6889 */ 6890 dbuf = NULL; 6891 } 6892 if (dbuf == NULL) 6893 dbuf = stmf_alloc_dbuf(task, minsz, &minsz, 0); 6894 if ((dbuf == NULL) || (dbuf->db_sglist[0].seg_length < sz)) { 6895 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6896 STMF_ALLOC_FAILURE, NULL); 6897 return; 6898 } 6899 dbuf->db_lu_private = NULL; 6900 6901 p = dbuf->db_sglist[0].seg_addr; 6902 6903 /* 6904 * Standard inquiry handling only. 6905 */ 6906 6907 bzero(p, inq_page_length + 5); 6908 6909 p[0] = DPQ_SUPPORTED | DTYPE_UNKNOWN; 6910 p[2] = 5; 6911 p[3] = 0x12; 6912 p[4] = inq_page_length; 6913 p[6] = 0x80; 6914 6915 (void) strncpy((char *)p+8, "SUN ", 8); 6916 (void) strncpy((char *)p+16, "COMSTAR ", 16); 6917 (void) strncpy((char *)p+32, "1.0 ", 4); 6918 6919 dbuf->db_data_size = sz; 6920 dbuf->db_relative_offset = 0; 6921 dbuf->db_flags = DB_DIRECTION_TO_RPORT; 6922 (void) stmf_xfer_data(task, dbuf, 0); 6923 6924 return; 6925 6926 case SCMD_REPORT_LUNS: 6927 task->task_cmd_xfer_length = 6928 ((((uint32_t)task->task_cdb[6]) << 24) | 6929 (((uint32_t)task->task_cdb[7]) << 16) | 6930 (((uint32_t)task->task_cdb[8]) << 8) | 6931 ((uint32_t)task->task_cdb[9])); 6932 6933 if (task->task_additional_flags & 6934 TASK_AF_NO_EXPECTED_XFER_LENGTH) { 6935 task->task_expected_xfer_length = 6936 task->task_cmd_xfer_length; 6937 } 6938 6939 sz = min(task->task_expected_xfer_length, 6940 task->task_cmd_xfer_length); 6941 6942 if (sz < 16) { 6943 stmf_scsilib_send_status(task, STATUS_CHECK, 6944 STMF_SAA_INVALID_FIELD_IN_CDB); 6945 return; 6946 } 6947 6948 iss = (stmf_i_scsi_session_t *) 6949 task->task_session->ss_stmf_private; 6950 rw_enter(iss->iss_lockp, RW_WRITER); 6951 xd = stmf_session_prepare_report_lun_data(iss->iss_sm); 6952 rw_exit(iss->iss_lockp); 6953 6954 if (xd == NULL) { 6955 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6956 STMF_ALLOC_FAILURE, NULL); 6957 return; 6958 } 6959 6960 sz = min(sz, xd->size_left); 6961 xd->size_left = sz; 6962 minsz = min(512, sz); 6963 6964 if (dbuf == NULL) 6965 dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0); 6966 if (dbuf == NULL) { 6967 kmem_free(xd, xd->alloc_size); 6968 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6969 STMF_ALLOC_FAILURE, NULL); 6970 return; 6971 } 6972 dbuf->db_lu_private = xd; 6973 stmf_xd_to_dbuf(dbuf, 1); 6974 6975 atomic_and_32(&iss->iss_flags, 6976 ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS)); 6977 dbuf->db_flags = DB_DIRECTION_TO_RPORT; 6978 (void) stmf_xfer_data(task, dbuf, 0); 6979 return; 6980 } 6981 6982 stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE); 6983 } 6984 6985 void 6986 stmf_dlun0_dbuf_done(scsi_task_t *task, stmf_data_buf_t *dbuf) 6987 { 6988 stmf_i_scsi_task_t *itask = 6989 (stmf_i_scsi_task_t *)task->task_stmf_private; 6990 6991 if (dbuf->db_xfer_status != STMF_SUCCESS) { 6992 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6993 dbuf->db_xfer_status, NULL); 6994 return; 6995 } 6996 task->task_nbytes_transferred += dbuf->db_data_size; 6997 if (dbuf->db_lu_private) { 6998 /* There is more */ 6999 stmf_xd_to_dbuf(dbuf, 1); 7000 (void) stmf_xfer_data(task, dbuf, 0); 7001 return; 7002 } 7003 7004 stmf_free_dbuf(task, dbuf); 7005 /* 7006 * If this is a proxy task, it will need to be completed from the 7007 * proxy port provider. This message lets pppt know that the xfer 7008 * is complete. When we receive the status from pppt, we will 7009 * then relay that status back to the lport. 7010 */ 7011 if (itask->itask_flags & ITASK_PROXY_TASK) { 7012 stmf_ic_msg_t *ic_xfer_done_msg = NULL; 7013 stmf_status_t ic_ret = STMF_FAILURE; 7014 uint64_t session_msg_id; 7015 mutex_enter(&stmf_state.stmf_lock); 7016 session_msg_id = stmf_proxy_msg_id++; 7017 mutex_exit(&stmf_state.stmf_lock); 7018 /* send xfer done status to pppt */ 7019 ic_xfer_done_msg = ic_scsi_data_xfer_done_msg_alloc( 7020 itask->itask_proxy_msg_id, 7021 task->task_session->ss_session_id, 7022 STMF_SUCCESS, session_msg_id); 7023 if (ic_xfer_done_msg) { 7024 ic_ret = ic_tx_msg(ic_xfer_done_msg); 7025 if (ic_ret != STMF_IC_MSG_SUCCESS) { 7026 cmn_err(CE_WARN, "unable to xmit session msg"); 7027 } 7028 } 7029 /* task will be completed from pppt */ 7030 return; 7031 } 7032 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 7033 } 7034 7035 /* ARGSUSED */ 7036 void 7037 stmf_dlun0_status_done(scsi_task_t *task) 7038 { 7039 } 7040 7041 /* ARGSUSED */ 7042 void 7043 stmf_dlun0_task_free(scsi_task_t *task) 7044 { 7045 } 7046 7047 /* ARGSUSED */ 7048 stmf_status_t 7049 stmf_dlun0_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags) 7050 { 7051 scsi_task_t *task = (scsi_task_t *)arg; 7052 stmf_i_scsi_task_t *itask = 7053 (stmf_i_scsi_task_t *)task->task_stmf_private; 7054 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 7055 int i; 7056 uint8_t map; 7057 7058 if ((task->task_mgmt_function) && (itask->itask_flags & 7059 (ITASK_CAUSING_LU_RESET | ITASK_CAUSING_TARGET_RESET))) { 7060 switch (task->task_mgmt_function) { 7061 case TM_ABORT_TASK: 7062 case TM_ABORT_TASK_SET: 7063 case TM_CLEAR_TASK_SET: 7064 case TM_LUN_RESET: 7065 atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE); 7066 break; 7067 case TM_TARGET_RESET: 7068 case TM_TARGET_COLD_RESET: 7069 case TM_TARGET_WARM_RESET: 7070 stmf_abort_target_reset(task); 7071 break; 7072 } 7073 return (STMF_ABORT_SUCCESS); 7074 } 7075 7076 /* 7077 * OK so its not a task mgmt. Make sure we free any xd sitting 7078 * inside any dbuf. 7079 */ 7080 if ((map = itask->itask_allocated_buf_map) != 0) { 7081 for (i = 0; i < 4; i++) { 7082 if ((map & 1) && 7083 ((itask->itask_dbufs[i])->db_lu_private)) { 7084 stmf_xfer_data_t *xd; 7085 stmf_data_buf_t *dbuf; 7086 7087 dbuf = itask->itask_dbufs[i]; 7088 xd = (stmf_xfer_data_t *)dbuf->db_lu_private; 7089 dbuf->db_lu_private = NULL; 7090 kmem_free(xd, xd->alloc_size); 7091 } 7092 map >>= 1; 7093 } 7094 } 7095 return (STMF_ABORT_SUCCESS); 7096 } 7097 7098 void 7099 stmf_dlun0_task_poll(struct scsi_task *task) 7100 { 7101 /* Right now we only do this for handling task management functions */ 7102 ASSERT(task->task_mgmt_function); 7103 7104 switch (task->task_mgmt_function) { 7105 case TM_ABORT_TASK: 7106 case TM_ABORT_TASK_SET: 7107 case TM_CLEAR_TASK_SET: 7108 case TM_LUN_RESET: 7109 (void) stmf_lun_reset_poll(task->task_lu, task, 0); 7110 return; 7111 case TM_TARGET_RESET: 7112 case TM_TARGET_COLD_RESET: 7113 case TM_TARGET_WARM_RESET: 7114 stmf_target_reset_poll(task); 7115 return; 7116 } 7117 } 7118 7119 /* ARGSUSED */ 7120 void 7121 stmf_dlun0_ctl(struct stmf_lu *lu, int cmd, void *arg) 7122 { 7123 /* This function will never be called */ 7124 cmn_err(CE_WARN, "stmf_dlun0_ctl called with cmd %x", cmd); 7125 } 7126 7127 void 7128 stmf_dlun_init() 7129 { 7130 stmf_i_lu_t *ilu; 7131 7132 dlun0 = stmf_alloc(STMF_STRUCT_STMF_LU, 0, 0); 7133 dlun0->lu_task_alloc = stmf_dlun0_task_alloc; 7134 dlun0->lu_new_task = stmf_dlun0_new_task; 7135 dlun0->lu_dbuf_xfer_done = stmf_dlun0_dbuf_done; 7136 dlun0->lu_send_status_done = stmf_dlun0_status_done; 7137 dlun0->lu_task_free = stmf_dlun0_task_free; 7138 dlun0->lu_abort = stmf_dlun0_abort; 7139 dlun0->lu_task_poll = stmf_dlun0_task_poll; 7140 dlun0->lu_ctl = stmf_dlun0_ctl; 7141 7142 ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private; 7143 ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1; 7144 } 7145 7146 stmf_status_t 7147 stmf_dlun_fini() 7148 { 7149 stmf_i_lu_t *ilu; 7150 7151 ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private; 7152 7153 ASSERT(ilu->ilu_ntasks == ilu->ilu_ntasks_free); 7154 if (ilu->ilu_ntasks) { 7155 stmf_i_scsi_task_t *itask, *nitask; 7156 7157 nitask = ilu->ilu_tasks; 7158 do { 7159 itask = nitask; 7160 nitask = itask->itask_lu_next; 7161 dlun0->lu_task_free(itask->itask_task); 7162 stmf_free(itask->itask_task); 7163 } while (nitask != NULL); 7164 7165 } 7166 stmf_free(dlun0); 7167 return (STMF_SUCCESS); 7168 } 7169 7170 void 7171 stmf_abort_target_reset(scsi_task_t *task) 7172 { 7173 stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *) 7174 task->task_session->ss_stmf_private; 7175 stmf_lun_map_t *lm; 7176 stmf_lun_map_ent_t *lm_ent; 7177 stmf_i_lu_t *ilu; 7178 int i; 7179 7180 rw_enter(iss->iss_lockp, RW_READER); 7181 lm = iss->iss_sm; 7182 for (i = 0; i < lm->lm_nentries; i++) { 7183 if (lm->lm_plus[i] == NULL) 7184 continue; 7185 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 7186 ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private; 7187 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 7188 atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE); 7189 } 7190 } 7191 atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE); 7192 rw_exit(iss->iss_lockp); 7193 } 7194 7195 /* 7196 * The return value is only used by function managing target reset. 7197 */ 7198 stmf_status_t 7199 stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task, int target_reset) 7200 { 7201 stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 7202 int ntasks_pending; 7203 7204 ntasks_pending = ilu->ilu_ntasks - ilu->ilu_ntasks_free; 7205 /* 7206 * This function is also used during Target reset. The idea is that 7207 * once all the commands are aborted, call the LU's reset entry 7208 * point (abort entry point with a reset flag). But if this Task 7209 * mgmt is running on this LU then all the tasks cannot be aborted. 7210 * one task (this task) will still be running which is OK. 7211 */ 7212 if ((ntasks_pending == 0) || ((task->task_lu == lu) && 7213 (ntasks_pending == 1))) { 7214 stmf_status_t ret; 7215 7216 if ((task->task_mgmt_function == TM_LUN_RESET) || 7217 (task->task_mgmt_function == TM_TARGET_RESET) || 7218 (task->task_mgmt_function == TM_TARGET_WARM_RESET) || 7219 (task->task_mgmt_function == TM_TARGET_COLD_RESET)) { 7220 ret = lu->lu_abort(lu, STMF_LU_RESET_STATE, task, 0); 7221 } else { 7222 ret = STMF_SUCCESS; 7223 } 7224 if (ret == STMF_SUCCESS) { 7225 atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE); 7226 } 7227 if (target_reset) { 7228 return (ret); 7229 } 7230 if (ret == STMF_SUCCESS) { 7231 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 7232 return (ret); 7233 } 7234 if (ret != STMF_BUSY) { 7235 stmf_abort(STMF_QUEUE_TASK_ABORT, task, ret, NULL); 7236 return (ret); 7237 } 7238 } 7239 7240 if (target_reset) { 7241 /* Tell target reset polling code that we are not done */ 7242 return (STMF_BUSY); 7243 } 7244 7245 if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT) 7246 != STMF_SUCCESS) { 7247 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 7248 STMF_ALLOC_FAILURE, NULL); 7249 return (STMF_SUCCESS); 7250 } 7251 7252 return (STMF_SUCCESS); 7253 } 7254 7255 void 7256 stmf_target_reset_poll(struct scsi_task *task) 7257 { 7258 stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *) 7259 task->task_session->ss_stmf_private; 7260 stmf_lun_map_t *lm; 7261 stmf_lun_map_ent_t *lm_ent; 7262 stmf_i_lu_t *ilu; 7263 stmf_status_t ret; 7264 int i; 7265 int not_done = 0; 7266 7267 ASSERT(iss->iss_flags & ISS_RESET_ACTIVE); 7268 7269 rw_enter(iss->iss_lockp, RW_READER); 7270 lm = iss->iss_sm; 7271 for (i = 0; i < lm->lm_nentries; i++) { 7272 if (lm->lm_plus[i] == NULL) 7273 continue; 7274 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 7275 ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private; 7276 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 7277 rw_exit(iss->iss_lockp); 7278 ret = stmf_lun_reset_poll(lm_ent->ent_lu, task, 1); 7279 rw_enter(iss->iss_lockp, RW_READER); 7280 if (ret == STMF_SUCCESS) 7281 continue; 7282 not_done = 1; 7283 if (ret != STMF_BUSY) { 7284 rw_exit(iss->iss_lockp); 7285 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 7286 STMF_ABORTED, NULL); 7287 return; 7288 } 7289 } 7290 } 7291 rw_exit(iss->iss_lockp); 7292 7293 if (not_done) { 7294 if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT) 7295 != STMF_SUCCESS) { 7296 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 7297 STMF_ALLOC_FAILURE, NULL); 7298 return; 7299 } 7300 return; 7301 } 7302 7303 atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE); 7304 7305 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 7306 } 7307 7308 stmf_status_t 7309 stmf_lu_add_event(stmf_lu_t *lu, int eventid) 7310 { 7311 stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 7312 7313 if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) { 7314 return (STMF_INVALID_ARG); 7315 } 7316 7317 STMF_EVENT_ADD(ilu->ilu_event_hdl, eventid); 7318 return (STMF_SUCCESS); 7319 } 7320 7321 stmf_status_t 7322 stmf_lu_remove_event(stmf_lu_t *lu, int eventid) 7323 { 7324 stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 7325 7326 if (eventid == STMF_EVENT_ALL) { 7327 STMF_EVENT_CLEAR_ALL(ilu->ilu_event_hdl); 7328 return (STMF_SUCCESS); 7329 } 7330 7331 if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) { 7332 return (STMF_INVALID_ARG); 7333 } 7334 7335 STMF_EVENT_REMOVE(ilu->ilu_event_hdl, eventid); 7336 return (STMF_SUCCESS); 7337 } 7338 7339 stmf_status_t 7340 stmf_lport_add_event(stmf_local_port_t *lport, int eventid) 7341 { 7342 stmf_i_local_port_t *ilport = 7343 (stmf_i_local_port_t *)lport->lport_stmf_private; 7344 7345 if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) { 7346 return (STMF_INVALID_ARG); 7347 } 7348 7349 STMF_EVENT_ADD(ilport->ilport_event_hdl, eventid); 7350 return (STMF_SUCCESS); 7351 } 7352 7353 stmf_status_t 7354 stmf_lport_remove_event(stmf_local_port_t *lport, int eventid) 7355 { 7356 stmf_i_local_port_t *ilport = 7357 (stmf_i_local_port_t *)lport->lport_stmf_private; 7358 7359 if (eventid == STMF_EVENT_ALL) { 7360 STMF_EVENT_CLEAR_ALL(ilport->ilport_event_hdl); 7361 return (STMF_SUCCESS); 7362 } 7363 7364 if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) { 7365 return (STMF_INVALID_ARG); 7366 } 7367 7368 STMF_EVENT_REMOVE(ilport->ilport_event_hdl, eventid); 7369 return (STMF_SUCCESS); 7370 } 7371 7372 void 7373 stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid, void *arg, uint32_t flags) 7374 { 7375 if (STMF_EVENT_ENABLED(ilu->ilu_event_hdl, eventid) && 7376 (ilu->ilu_lu->lu_event_handler != NULL)) { 7377 ilu->ilu_lu->lu_event_handler(ilu->ilu_lu, eventid, arg, flags); 7378 } 7379 } 7380 7381 void 7382 stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid, void *arg, 7383 uint32_t flags) 7384 { 7385 if (STMF_EVENT_ENABLED(ilport->ilport_event_hdl, eventid) && 7386 (ilport->ilport_lport->lport_event_handler != NULL)) { 7387 ilport->ilport_lport->lport_event_handler( 7388 ilport->ilport_lport, eventid, arg, flags); 7389 } 7390 } 7391 7392 /* 7393 * With the possibility of having multiple itl sessions pointing to the 7394 * same itl_kstat_info, the ilu_kstat_lock mutex is used to synchronize 7395 * the kstat update of the ilu_kstat_io, itl_kstat_taskq and itl_kstat_lu_xfer 7396 * statistics. 7397 */ 7398 void 7399 stmf_itl_task_start(stmf_i_scsi_task_t *itask) 7400 { 7401 stmf_itl_data_t *itl = itask->itask_itl_datap; 7402 scsi_task_t *task = itask->itask_task; 7403 stmf_i_lu_t *ilu; 7404 7405 if (itl == NULL || task->task_lu == dlun0) 7406 return; 7407 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 7408 mutex_enter(ilu->ilu_kstat_io->ks_lock); 7409 itask->itask_start_timestamp = gethrtime(); 7410 kstat_waitq_enter(KSTAT_IO_PTR(itl->itl_kstat_taskq)); 7411 stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_enter); 7412 mutex_exit(ilu->ilu_kstat_io->ks_lock); 7413 7414 stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_enter); 7415 } 7416 7417 void 7418 stmf_itl_lu_new_task(stmf_i_scsi_task_t *itask) 7419 { 7420 stmf_itl_data_t *itl = itask->itask_itl_datap; 7421 scsi_task_t *task = itask->itask_task; 7422 stmf_i_lu_t *ilu; 7423 7424 if (itl == NULL || task->task_lu == dlun0) 7425 return; 7426 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 7427 mutex_enter(ilu->ilu_kstat_io->ks_lock); 7428 kstat_waitq_to_runq(KSTAT_IO_PTR(itl->itl_kstat_taskq)); 7429 stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_to_runq); 7430 mutex_exit(ilu->ilu_kstat_io->ks_lock); 7431 7432 stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_to_runq); 7433 } 7434 7435 void 7436 stmf_itl_task_done(stmf_i_scsi_task_t *itask) 7437 { 7438 stmf_itl_data_t *itl = itask->itask_itl_datap; 7439 scsi_task_t *task = itask->itask_task; 7440 kstat_io_t *kip; 7441 hrtime_t elapsed_time; 7442 stmf_kstat_itl_info_t *itli; 7443 stmf_i_lu_t *ilu; 7444 7445 if (itl == NULL || task->task_lu == dlun0) 7446 return; 7447 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 7448 7449 mutex_enter(ilu->ilu_kstat_io->ks_lock); 7450 itli = (stmf_kstat_itl_info_t *)KSTAT_NAMED_PTR(itl->itl_kstat_info); 7451 kip = KSTAT_IO_PTR(itl->itl_kstat_taskq); 7452 7453 itli->i_task_waitq_elapsed.value.ui64 += itask->itask_waitq_time; 7454 7455 itask->itask_done_timestamp = gethrtime(); 7456 elapsed_time = 7457 itask->itask_done_timestamp - itask->itask_start_timestamp; 7458 7459 if (task->task_flags & TF_READ_DATA) { 7460 kip->reads++; 7461 kip->nread += itask->itask_read_xfer; 7462 itli->i_task_read_elapsed.value.ui64 += elapsed_time; 7463 itli->i_lu_read_elapsed.value.ui64 += 7464 itask->itask_lu_read_time; 7465 itli->i_lport_read_elapsed.value.ui64 += 7466 itask->itask_lport_read_time; 7467 } 7468 7469 if (task->task_flags & TF_WRITE_DATA) { 7470 kip->writes++; 7471 kip->nwritten += itask->itask_write_xfer; 7472 itli->i_task_write_elapsed.value.ui64 += elapsed_time; 7473 itli->i_lu_write_elapsed.value.ui64 += 7474 itask->itask_lu_write_time; 7475 itli->i_lport_write_elapsed.value.ui64 += 7476 itask->itask_lport_write_time; 7477 } 7478 7479 if (itask->itask_flags & ITASK_KSTAT_IN_RUNQ) { 7480 kstat_runq_exit(kip); 7481 stmf_update_kstat_lu_q(task, kstat_runq_exit); 7482 mutex_exit(ilu->ilu_kstat_io->ks_lock); 7483 stmf_update_kstat_lport_q(task, kstat_runq_exit); 7484 } else { 7485 kstat_waitq_exit(kip); 7486 stmf_update_kstat_lu_q(task, kstat_waitq_exit); 7487 mutex_exit(ilu->ilu_kstat_io->ks_lock); 7488 stmf_update_kstat_lport_q(task, kstat_waitq_exit); 7489 } 7490 } 7491 7492 void 7493 stmf_lu_xfer_start(scsi_task_t *task) 7494 { 7495 stmf_i_scsi_task_t *itask = task->task_stmf_private; 7496 stmf_itl_data_t *itl = itask->itask_itl_datap; 7497 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 7498 kstat_io_t *kip; 7499 7500 if (itl == NULL || task->task_lu == dlun0) 7501 return; 7502 7503 kip = KSTAT_IO_PTR(itl->itl_kstat_lu_xfer); 7504 mutex_enter(ilu->ilu_kstat_io->ks_lock); 7505 kstat_runq_enter(kip); 7506 mutex_exit(ilu->ilu_kstat_io->ks_lock); 7507 } 7508 7509 void 7510 stmf_lu_xfer_done(scsi_task_t *task, boolean_t read, uint64_t xfer_bytes, 7511 hrtime_t elapsed_time) 7512 { 7513 stmf_i_scsi_task_t *itask = task->task_stmf_private; 7514 stmf_itl_data_t *itl = itask->itask_itl_datap; 7515 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 7516 kstat_io_t *kip; 7517 7518 if (itl == NULL || task->task_lu == dlun0) 7519 return; 7520 7521 if (read) { 7522 atomic_add_64((uint64_t *)&itask->itask_lu_read_time, 7523 elapsed_time); 7524 } else { 7525 atomic_add_64((uint64_t *)&itask->itask_lu_write_time, 7526 elapsed_time); 7527 } 7528 7529 kip = KSTAT_IO_PTR(itl->itl_kstat_lu_xfer); 7530 mutex_enter(ilu->ilu_kstat_io->ks_lock); 7531 kstat_runq_exit(kip); 7532 if (read) { 7533 kip->reads++; 7534 kip->nread += xfer_bytes; 7535 } else { 7536 kip->writes++; 7537 kip->nwritten += xfer_bytes; 7538 } 7539 mutex_exit(ilu->ilu_kstat_io->ks_lock); 7540 } 7541 7542 static void 7543 stmf_lport_xfer_start(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf) 7544 { 7545 stmf_itl_data_t *itl = itask->itask_itl_datap; 7546 7547 if (itl == NULL) 7548 return; 7549 7550 DTRACE_PROBE2(scsi__xfer__start, scsi_task_t *, itask->itask_task, 7551 stmf_data_buf_t *, dbuf); 7552 7553 dbuf->db_xfer_start_timestamp = gethrtime(); 7554 } 7555 7556 static void 7557 stmf_lport_xfer_done(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf) 7558 { 7559 stmf_itl_data_t *itl = itask->itask_itl_datap; 7560 scsi_task_t *task; 7561 stmf_i_local_port_t *ilp; 7562 kstat_io_t *kip; 7563 hrtime_t elapsed_time; 7564 uint64_t xfer_size; 7565 7566 if (itl == NULL) 7567 return; 7568 7569 task = (scsi_task_t *)itask->itask_task; 7570 ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private; 7571 xfer_size = (dbuf->db_xfer_status == STMF_SUCCESS) ? 7572 dbuf->db_data_size : 0; 7573 7574 elapsed_time = gethrtime() - dbuf->db_xfer_start_timestamp; 7575 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { 7576 atomic_add_64((uint64_t *)&itask->itask_lport_read_time, 7577 elapsed_time); 7578 atomic_add_64((uint64_t *)&itask->itask_read_xfer, 7579 xfer_size); 7580 } else { 7581 atomic_add_64((uint64_t *)&itask->itask_lport_write_time, 7582 elapsed_time); 7583 atomic_add_64((uint64_t *)&itask->itask_write_xfer, 7584 xfer_size); 7585 } 7586 7587 DTRACE_PROBE3(scsi__xfer__end, scsi_task_t *, itask->itask_task, 7588 stmf_data_buf_t *, dbuf, hrtime_t, elapsed_time); 7589 7590 kip = KSTAT_IO_PTR(itl->itl_kstat_lport_xfer); 7591 mutex_enter(ilp->ilport_kstat_io->ks_lock); 7592 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { 7593 kip->reads++; 7594 kip->nread += xfer_size; 7595 } else { 7596 kip->writes++; 7597 kip->nwritten += xfer_size; 7598 } 7599 mutex_exit(ilp->ilport_kstat_io->ks_lock); 7600 7601 dbuf->db_xfer_start_timestamp = 0; 7602 } 7603 7604 void 7605 stmf_svc_init() 7606 { 7607 if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) 7608 return; 7609 stmf_state.stmf_svc_taskq = ddi_taskq_create(0, "STMF_SVC_TASKQ", 1, 7610 TASKQ_DEFAULTPRI, 0); 7611 (void) ddi_taskq_dispatch(stmf_state.stmf_svc_taskq, 7612 stmf_svc, 0, DDI_SLEEP); 7613 } 7614 7615 stmf_status_t 7616 stmf_svc_fini() 7617 { 7618 uint32_t i; 7619 7620 mutex_enter(&stmf_state.stmf_lock); 7621 if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) { 7622 stmf_state.stmf_svc_flags |= STMF_SVC_TERMINATE; 7623 cv_signal(&stmf_state.stmf_cv); 7624 } 7625 mutex_exit(&stmf_state.stmf_lock); 7626 7627 /* Wait for 5 seconds */ 7628 for (i = 0; i < 500; i++) { 7629 if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) 7630 delay(drv_usectohz(10000)); 7631 else 7632 break; 7633 } 7634 if (i == 500) 7635 return (STMF_BUSY); 7636 7637 ddi_taskq_destroy(stmf_state.stmf_svc_taskq); 7638 7639 return (STMF_SUCCESS); 7640 } 7641 7642 /* ARGSUSED */ 7643 void 7644 stmf_svc(void *arg) 7645 { 7646 stmf_svc_req_t *req, **preq; 7647 clock_t td; 7648 clock_t drain_start, drain_next = 0; 7649 clock_t timing_start, timing_next = 0; 7650 clock_t worker_delay = 0; 7651 int deq; 7652 stmf_lu_t *lu; 7653 stmf_i_lu_t *ilu; 7654 stmf_local_port_t *lport; 7655 stmf_i_local_port_t *ilport, *next_ilport; 7656 stmf_i_scsi_session_t *iss; 7657 7658 td = drv_usectohz(20000); 7659 7660 mutex_enter(&stmf_state.stmf_lock); 7661 stmf_state.stmf_svc_flags |= STMF_SVC_STARTED | STMF_SVC_ACTIVE; 7662 7663 stmf_svc_loop: 7664 if (stmf_state.stmf_svc_flags & STMF_SVC_TERMINATE) { 7665 stmf_state.stmf_svc_flags &= 7666 ~(STMF_SVC_STARTED | STMF_SVC_ACTIVE); 7667 mutex_exit(&stmf_state.stmf_lock); 7668 return; 7669 } 7670 7671 if (stmf_state.stmf_svc_active) { 7672 int waitq_add = 0; 7673 req = stmf_state.stmf_svc_active; 7674 stmf_state.stmf_svc_active = req->svc_next; 7675 7676 switch (req->svc_cmd) { 7677 case STMF_CMD_LPORT_ONLINE: 7678 /* Fallthrough */ 7679 case STMF_CMD_LPORT_OFFLINE: 7680 /* Fallthrough */ 7681 case STMF_CMD_LU_ONLINE: 7682 /* Nothing to do */ 7683 waitq_add = 1; 7684 break; 7685 7686 case STMF_CMD_LU_OFFLINE: 7687 /* Remove all mappings of this LU */ 7688 stmf_session_lu_unmapall((stmf_lu_t *)req->svc_obj); 7689 /* Kill all the pending I/Os for this LU */ 7690 mutex_exit(&stmf_state.stmf_lock); 7691 stmf_task_lu_killall((stmf_lu_t *)req->svc_obj, NULL, 7692 STMF_ABORTED); 7693 mutex_enter(&stmf_state.stmf_lock); 7694 waitq_add = 1; 7695 break; 7696 default: 7697 cmn_err(CE_PANIC, "stmf_svc: unknown cmd %d", 7698 req->svc_cmd); 7699 } 7700 7701 if (waitq_add) { 7702 /* Put it in the wait queue */ 7703 req->svc_next = stmf_state.stmf_svc_waiting; 7704 stmf_state.stmf_svc_waiting = req; 7705 } 7706 } 7707 7708 /* The waiting list is not going to be modified by anybody else */ 7709 mutex_exit(&stmf_state.stmf_lock); 7710 7711 for (preq = &stmf_state.stmf_svc_waiting; (*preq) != NULL; ) { 7712 req = *preq; 7713 deq = 0; 7714 7715 switch (req->svc_cmd) { 7716 case STMF_CMD_LU_ONLINE: 7717 lu = (stmf_lu_t *)req->svc_obj; 7718 deq = 1; 7719 lu->lu_ctl(lu, req->svc_cmd, &req->svc_info); 7720 break; 7721 7722 case STMF_CMD_LU_OFFLINE: 7723 lu = (stmf_lu_t *)req->svc_obj; 7724 ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 7725 if (ilu->ilu_ntasks != ilu->ilu_ntasks_free) 7726 break; 7727 deq = 1; 7728 lu->lu_ctl(lu, req->svc_cmd, &req->svc_info); 7729 break; 7730 7731 case STMF_CMD_LPORT_OFFLINE: 7732 /* Fallthrough */ 7733 case STMF_CMD_LPORT_ONLINE: 7734 lport = (stmf_local_port_t *)req->svc_obj; 7735 deq = 1; 7736 lport->lport_ctl(lport, req->svc_cmd, &req->svc_info); 7737 break; 7738 } 7739 if (deq) { 7740 *preq = req->svc_next; 7741 kmem_free(req, req->svc_req_alloc_size); 7742 } else { 7743 preq = &req->svc_next; 7744 } 7745 } 7746 7747 mutex_enter(&stmf_state.stmf_lock); 7748 if (stmf_state.stmf_svc_active == NULL) { 7749 /* Do timeouts */ 7750 if (stmf_state.stmf_nlus && 7751 ((!timing_next) || (ddi_get_lbolt() >= timing_next))) { 7752 if (!stmf_state.stmf_svc_ilu_timing) { 7753 /* we are starting a new round */ 7754 stmf_state.stmf_svc_ilu_timing = 7755 stmf_state.stmf_ilulist; 7756 timing_start = ddi_get_lbolt(); 7757 } 7758 stmf_check_ilu_timing(); 7759 if (!stmf_state.stmf_svc_ilu_timing) { 7760 /* we finished a complete round */ 7761 timing_next = 7762 timing_start + drv_usectohz(5*1000*1000); 7763 } else { 7764 /* we still have some ilu items to check */ 7765 timing_next = 7766 ddi_get_lbolt() + drv_usectohz(1*1000*1000); 7767 } 7768 if (stmf_state.stmf_svc_active) 7769 goto stmf_svc_loop; 7770 } 7771 /* Check if there are free tasks to clear */ 7772 if (stmf_state.stmf_nlus && 7773 ((!drain_next) || (ddi_get_lbolt() >= drain_next))) { 7774 if (!stmf_state.stmf_svc_ilu_draining) { 7775 /* we are starting a new round */ 7776 stmf_state.stmf_svc_ilu_draining = 7777 stmf_state.stmf_ilulist; 7778 drain_start = ddi_get_lbolt(); 7779 } 7780 stmf_check_freetask(); 7781 if (!stmf_state.stmf_svc_ilu_draining) { 7782 /* we finished a complete round */ 7783 drain_next = 7784 drain_start + drv_usectohz(10*1000*1000); 7785 } else { 7786 /* we still have some ilu items to check */ 7787 drain_next = 7788 ddi_get_lbolt() + drv_usectohz(1*1000*1000); 7789 } 7790 if (stmf_state.stmf_svc_active) 7791 goto stmf_svc_loop; 7792 } 7793 7794 /* Check if we need to run worker_mgmt */ 7795 if (ddi_get_lbolt() > worker_delay) { 7796 stmf_worker_mgmt(); 7797 worker_delay = ddi_get_lbolt() + 7798 stmf_worker_mgmt_delay; 7799 } 7800 7801 /* Check if any active session got its 1st LUN */ 7802 if (stmf_state.stmf_process_initial_luns) { 7803 int stmf_level = 0; 7804 int port_level; 7805 for (ilport = stmf_state.stmf_ilportlist; ilport; 7806 ilport = next_ilport) { 7807 int ilport_lock_held; 7808 next_ilport = ilport->ilport_next; 7809 if ((ilport->ilport_flags & 7810 ILPORT_SS_GOT_INITIAL_LUNS) == 0) { 7811 continue; 7812 } 7813 port_level = 0; 7814 rw_enter(&ilport->ilport_lock, RW_READER); 7815 ilport_lock_held = 1; 7816 for (iss = ilport->ilport_ss_list; iss; 7817 iss = iss->iss_next) { 7818 if ((iss->iss_flags & 7819 ISS_GOT_INITIAL_LUNS) == 0) { 7820 continue; 7821 } 7822 port_level++; 7823 stmf_level++; 7824 atomic_and_32(&iss->iss_flags, 7825 ~ISS_GOT_INITIAL_LUNS); 7826 atomic_or_32(&iss->iss_flags, 7827 ISS_EVENT_ACTIVE); 7828 rw_exit(&ilport->ilport_lock); 7829 ilport_lock_held = 0; 7830 mutex_exit(&stmf_state.stmf_lock); 7831 stmf_generate_lport_event(ilport, 7832 LPORT_EVENT_INITIAL_LUN_MAPPED, 7833 iss->iss_ss, 0); 7834 atomic_and_32(&iss->iss_flags, 7835 ~ISS_EVENT_ACTIVE); 7836 mutex_enter(&stmf_state.stmf_lock); 7837 /* 7838 * scan all the ilports again as the 7839 * ilport list might have changed. 7840 */ 7841 next_ilport = 7842 stmf_state.stmf_ilportlist; 7843 break; 7844 } 7845 if (port_level == 0) { 7846 atomic_and_32(&ilport->ilport_flags, 7847 ~ILPORT_SS_GOT_INITIAL_LUNS); 7848 } 7849 /* drop the lock if we are holding it. */ 7850 if (ilport_lock_held == 1) 7851 rw_exit(&ilport->ilport_lock); 7852 7853 /* Max 4 session at a time */ 7854 if (stmf_level >= 4) { 7855 break; 7856 } 7857 } 7858 if (stmf_level == 0) { 7859 stmf_state.stmf_process_initial_luns = 0; 7860 } 7861 } 7862 7863 stmf_state.stmf_svc_flags &= ~STMF_SVC_ACTIVE; 7864 (void) cv_reltimedwait(&stmf_state.stmf_cv, 7865 &stmf_state.stmf_lock, td, TR_CLOCK_TICK); 7866 stmf_state.stmf_svc_flags |= STMF_SVC_ACTIVE; 7867 } 7868 goto stmf_svc_loop; 7869 } 7870 7871 void 7872 stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info) 7873 { 7874 stmf_svc_req_t *req; 7875 int s; 7876 7877 ASSERT(!mutex_owned(&stmf_state.stmf_lock)); 7878 s = sizeof (stmf_svc_req_t); 7879 if (info->st_additional_info) { 7880 s += strlen(info->st_additional_info) + 1; 7881 } 7882 req = kmem_zalloc(s, KM_SLEEP); 7883 7884 req->svc_cmd = cmd; 7885 req->svc_obj = obj; 7886 req->svc_info.st_rflags = info->st_rflags; 7887 if (info->st_additional_info) { 7888 req->svc_info.st_additional_info = (char *)(GET_BYTE_OFFSET(req, 7889 sizeof (stmf_svc_req_t))); 7890 (void) strcpy(req->svc_info.st_additional_info, 7891 info->st_additional_info); 7892 } 7893 req->svc_req_alloc_size = s; 7894 7895 mutex_enter(&stmf_state.stmf_lock); 7896 req->svc_next = stmf_state.stmf_svc_active; 7897 stmf_state.stmf_svc_active = req; 7898 if ((stmf_state.stmf_svc_flags & STMF_SVC_ACTIVE) == 0) { 7899 cv_signal(&stmf_state.stmf_cv); 7900 } 7901 mutex_exit(&stmf_state.stmf_lock); 7902 } 7903 7904 void 7905 stmf_trace(caddr_t ident, const char *fmt, ...) 7906 { 7907 va_list args; 7908 char tbuf[160]; 7909 int len; 7910 7911 if (!stmf_trace_on) 7912 return; 7913 len = snprintf(tbuf, 158, "%s:%07lu: ", ident ? ident : "", 7914 ddi_get_lbolt()); 7915 va_start(args, fmt); 7916 len += vsnprintf(tbuf + len, 158 - len, fmt, args); 7917 va_end(args); 7918 7919 if (len > 158) { 7920 len = 158; 7921 } 7922 tbuf[len++] = '\n'; 7923 tbuf[len] = 0; 7924 7925 mutex_enter(&trace_buf_lock); 7926 bcopy(tbuf, &stmf_trace_buf[trace_buf_curndx], len+1); 7927 trace_buf_curndx += len; 7928 if (trace_buf_curndx > (trace_buf_size - 320)) 7929 trace_buf_curndx = 0; 7930 mutex_exit(&trace_buf_lock); 7931 } 7932 7933 void 7934 stmf_trace_clear() 7935 { 7936 if (!stmf_trace_on) 7937 return; 7938 mutex_enter(&trace_buf_lock); 7939 trace_buf_curndx = 0; 7940 if (trace_buf_size > 0) 7941 stmf_trace_buf[0] = 0; 7942 mutex_exit(&trace_buf_lock); 7943 } 7944 7945 static void 7946 stmf_abort_task_offline(scsi_task_t *task, int offline_lu, char *info) 7947 { 7948 stmf_state_change_info_t change_info; 7949 void *ctl_private; 7950 uint32_t ctl_cmd; 7951 int msg = 0; 7952 7953 stmf_trace("FROM STMF", "abort_task_offline called for %s: %s", 7954 offline_lu ? "LU" : "LPORT", info ? info : "no additional info"); 7955 change_info.st_additional_info = info; 7956 if (offline_lu) { 7957 change_info.st_rflags = STMF_RFLAG_RESET | 7958 STMF_RFLAG_LU_ABORT; 7959 ctl_private = task->task_lu; 7960 if (((stmf_i_lu_t *) 7961 task->task_lu->lu_stmf_private)->ilu_state == 7962 STMF_STATE_ONLINE) { 7963 msg = 1; 7964 } 7965 ctl_cmd = STMF_CMD_LU_OFFLINE; 7966 } else { 7967 change_info.st_rflags = STMF_RFLAG_RESET | 7968 STMF_RFLAG_LPORT_ABORT; 7969 ctl_private = task->task_lport; 7970 if (((stmf_i_local_port_t *) 7971 task->task_lport->lport_stmf_private)->ilport_state == 7972 STMF_STATE_ONLINE) { 7973 msg = 1; 7974 } 7975 ctl_cmd = STMF_CMD_LPORT_OFFLINE; 7976 } 7977 7978 if (msg) { 7979 stmf_trace(0, "Calling stmf_ctl to offline %s : %s", 7980 offline_lu ? "LU" : "LPORT", info ? info : 7981 "<no additional info>"); 7982 } 7983 (void) stmf_ctl(ctl_cmd, ctl_private, &change_info); 7984 } 7985