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