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