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