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 ret = STMF_ALREADY; 4865 goto stmf_ctl_lock_exit; 4866 } 4867 if (ilu->ilu_state != STMF_STATE_OFFLINE) { 4868 ret = STMF_INVALID_ARG; 4869 goto stmf_ctl_lock_exit; 4870 } 4871 ilu->ilu_state = STMF_STATE_ONLINING; 4872 mutex_exit(&stmf_state.stmf_lock); 4873 stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg); 4874 break; 4875 4876 case STMF_CMD_LU_ONLINE_COMPLETE: 4877 if (ilu->ilu_state != STMF_STATE_ONLINING) { 4878 ret = STMF_INVALID_ARG; 4879 goto stmf_ctl_lock_exit; 4880 } 4881 if (((stmf_change_status_t *)arg)->st_completion_status == 4882 STMF_SUCCESS) { 4883 ilu->ilu_state = STMF_STATE_ONLINE; 4884 mutex_exit(&stmf_state.stmf_lock); 4885 ((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj, 4886 STMF_ACK_LU_ONLINE_COMPLETE, arg); 4887 mutex_enter(&stmf_state.stmf_lock); 4888 stmf_add_lu_to_active_sessions((stmf_lu_t *)obj); 4889 } else { 4890 /* XXX: should throw a meesage an record more data */ 4891 ilu->ilu_state = STMF_STATE_OFFLINE; 4892 } 4893 ret = STMF_SUCCESS; 4894 goto stmf_ctl_lock_exit; 4895 4896 case STMF_CMD_LU_OFFLINE: 4897 if (ilu->ilu_state == STMF_STATE_OFFLINE) { 4898 ret = STMF_ALREADY; 4899 goto stmf_ctl_lock_exit; 4900 } 4901 if (ilu->ilu_state != STMF_STATE_ONLINE) { 4902 ret = STMF_INVALID_ARG; 4903 goto stmf_ctl_lock_exit; 4904 } 4905 ilu->ilu_state = STMF_STATE_OFFLINING; 4906 mutex_exit(&stmf_state.stmf_lock); 4907 stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg); 4908 break; 4909 4910 case STMF_CMD_LU_OFFLINE_COMPLETE: 4911 if (ilu->ilu_state != STMF_STATE_OFFLINING) { 4912 ret = STMF_INVALID_ARG; 4913 goto stmf_ctl_lock_exit; 4914 } 4915 if (((stmf_change_status_t *)arg)->st_completion_status == 4916 STMF_SUCCESS) { 4917 ilu->ilu_state = STMF_STATE_OFFLINE; 4918 mutex_exit(&stmf_state.stmf_lock); 4919 ((stmf_lu_t *)obj)->lu_ctl((stmf_lu_t *)obj, 4920 STMF_ACK_LU_OFFLINE_COMPLETE, arg); 4921 mutex_enter(&stmf_state.stmf_lock); 4922 } else { 4923 ilu->ilu_state = STMF_STATE_ONLINE; 4924 stmf_add_lu_to_active_sessions((stmf_lu_t *)obj); 4925 } 4926 mutex_exit(&stmf_state.stmf_lock); 4927 break; 4928 4929 /* 4930 * LPORT_ONLINE/OFFLINE has nothing to do with link offline/online. 4931 * It's related with hardware disable/enable. 4932 */ 4933 case STMF_CMD_LPORT_ONLINE: 4934 if (ilport->ilport_state == STMF_STATE_ONLINE) { 4935 ret = STMF_ALREADY; 4936 goto stmf_ctl_lock_exit; 4937 } 4938 if (ilport->ilport_state != STMF_STATE_OFFLINE) { 4939 ret = STMF_INVALID_ARG; 4940 goto stmf_ctl_lock_exit; 4941 } 4942 4943 /* 4944 * Only user request can recover the port from the 4945 * FORCED_OFFLINE state 4946 */ 4947 if (ilport->ilport_flags & ILPORT_FORCED_OFFLINE) { 4948 if (!(ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) { 4949 ret = STMF_FAILURE; 4950 goto stmf_ctl_lock_exit; 4951 } 4952 } 4953 4954 /* 4955 * Avoid too frequent request to online 4956 */ 4957 if (ssci->st_rflags & STMF_RFLAG_USER_REQUEST) { 4958 ilport->ilport_online_times = 0; 4959 ilport->ilport_avg_interval = 0; 4960 } 4961 if ((ilport->ilport_avg_interval < STMF_AVG_ONLINE_INTERVAL) && 4962 (ilport->ilport_online_times >= 4)) { 4963 ret = STMF_FAILURE; 4964 ilport->ilport_flags |= ILPORT_FORCED_OFFLINE; 4965 stmf_trace(NULL, "stmf_ctl: too frequent request to " 4966 "online the port"); 4967 cmn_err(CE_WARN, "stmf_ctl: too frequent request to " 4968 "online the port, set FORCED_OFFLINE now"); 4969 goto stmf_ctl_lock_exit; 4970 } 4971 if (ilport->ilport_online_times > 0) { 4972 if (ilport->ilport_online_times == 1) { 4973 ilport->ilport_avg_interval = ddi_get_lbolt() - 4974 ilport->ilport_last_online_clock; 4975 } else { 4976 ilport->ilport_avg_interval = 4977 (ilport->ilport_avg_interval + 4978 ddi_get_lbolt() - 4979 ilport->ilport_last_online_clock) >> 1; 4980 } 4981 } 4982 ilport->ilport_last_online_clock = ddi_get_lbolt(); 4983 ilport->ilport_online_times++; 4984 4985 /* 4986 * Submit online service request 4987 */ 4988 ilport->ilport_flags &= ~ILPORT_FORCED_OFFLINE; 4989 ilport->ilport_state = STMF_STATE_ONLINING; 4990 mutex_exit(&stmf_state.stmf_lock); 4991 stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg); 4992 break; 4993 4994 case STMF_CMD_LPORT_ONLINE_COMPLETE: 4995 if (ilport->ilport_state != STMF_STATE_ONLINING) { 4996 ret = STMF_INVALID_ARG; 4997 goto stmf_ctl_lock_exit; 4998 } 4999 if (((stmf_change_status_t *)arg)->st_completion_status == 5000 STMF_SUCCESS) { 5001 ilport->ilport_state = STMF_STATE_ONLINE; 5002 mutex_exit(&stmf_state.stmf_lock); 5003 ((stmf_local_port_t *)obj)->lport_ctl( 5004 (stmf_local_port_t *)obj, 5005 STMF_ACK_LPORT_ONLINE_COMPLETE, arg); 5006 mutex_enter(&stmf_state.stmf_lock); 5007 } else { 5008 ilport->ilport_state = STMF_STATE_OFFLINE; 5009 } 5010 ret = STMF_SUCCESS; 5011 goto stmf_ctl_lock_exit; 5012 5013 case STMF_CMD_LPORT_OFFLINE: 5014 if (ilport->ilport_state == STMF_STATE_OFFLINE) { 5015 ret = STMF_ALREADY; 5016 goto stmf_ctl_lock_exit; 5017 } 5018 if (ilport->ilport_state != STMF_STATE_ONLINE) { 5019 ret = STMF_INVALID_ARG; 5020 goto stmf_ctl_lock_exit; 5021 } 5022 ilport->ilport_state = STMF_STATE_OFFLINING; 5023 mutex_exit(&stmf_state.stmf_lock); 5024 stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg); 5025 break; 5026 5027 case STMF_CMD_LPORT_OFFLINE_COMPLETE: 5028 if (ilport->ilport_state != STMF_STATE_OFFLINING) { 5029 ret = STMF_INVALID_ARG; 5030 goto stmf_ctl_lock_exit; 5031 } 5032 if (((stmf_change_status_t *)arg)->st_completion_status == 5033 STMF_SUCCESS) { 5034 ilport->ilport_state = STMF_STATE_OFFLINE; 5035 mutex_exit(&stmf_state.stmf_lock); 5036 ((stmf_local_port_t *)obj)->lport_ctl( 5037 (stmf_local_port_t *)obj, 5038 STMF_ACK_LPORT_OFFLINE_COMPLETE, arg); 5039 mutex_enter(&stmf_state.stmf_lock); 5040 } else { 5041 ilport->ilport_state = STMF_STATE_ONLINE; 5042 } 5043 mutex_exit(&stmf_state.stmf_lock); 5044 break; 5045 5046 default: 5047 cmn_err(CE_WARN, "Invalid ctl cmd received %x", cmd); 5048 ret = STMF_INVALID_ARG; 5049 goto stmf_ctl_lock_exit; 5050 } 5051 5052 return (STMF_SUCCESS); 5053 5054 stmf_ctl_lock_exit:; 5055 mutex_exit(&stmf_state.stmf_lock); 5056 return (ret); 5057 } 5058 5059 /* ARGSUSED */ 5060 stmf_status_t 5061 stmf_info_impl(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf, 5062 uint32_t *bufsizep) 5063 { 5064 return (STMF_NOT_SUPPORTED); 5065 } 5066 5067 /* ARGSUSED */ 5068 stmf_status_t 5069 stmf_info(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf, 5070 uint32_t *bufsizep) 5071 { 5072 uint32_t cl = SI_GET_CLASS(cmd); 5073 5074 if (cl == SI_STMF) { 5075 return (stmf_info_impl(cmd, arg1, arg2, buf, bufsizep)); 5076 } 5077 if (cl == SI_LPORT) { 5078 return (((stmf_local_port_t *)arg1)->lport_info(cmd, arg1, 5079 arg2, buf, bufsizep)); 5080 } else if (cl == SI_LU) { 5081 return (((stmf_lu_t *)arg1)->lu_info(cmd, arg1, arg2, buf, 5082 bufsizep)); 5083 } 5084 5085 return (STMF_NOT_SUPPORTED); 5086 } 5087 5088 /* 5089 * Used by port providers. pwwn is 8 byte wwn, sdid is the devid used by 5090 * stmf to register local ports. The ident should have 20 bytes in buffer 5091 * space to convert the wwn to "wwn.xxxxxxxxxxxxxxxx" string. 5092 */ 5093 void 5094 stmf_wwn_to_devid_desc(scsi_devid_desc_t *sdid, uint8_t *wwn, 5095 uint8_t protocol_id) 5096 { 5097 char wwn_str[20+1]; 5098 5099 sdid->protocol_id = protocol_id; 5100 sdid->piv = 1; 5101 sdid->code_set = CODE_SET_ASCII; 5102 sdid->association = ID_IS_TARGET_PORT; 5103 sdid->ident_length = 20; 5104 /* Convert wwn value to "wwn.XXXXXXXXXXXXXXXX" format */ 5105 (void) snprintf(wwn_str, sizeof (wwn_str), 5106 "wwn.%02X%02X%02X%02X%02X%02X%02X%02X", 5107 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 5108 bcopy(wwn_str, (char *)sdid->ident, 20); 5109 } 5110 5111 5112 stmf_xfer_data_t * 5113 stmf_prepare_tpgs_data(uint8_t ilu_alua) 5114 { 5115 stmf_xfer_data_t *xd; 5116 stmf_i_local_port_t *ilport; 5117 uint8_t *p; 5118 uint32_t sz, asz, nports = 0, nports_standby = 0; 5119 5120 mutex_enter(&stmf_state.stmf_lock); 5121 /* check if any ports are standby and create second group */ 5122 for (ilport = stmf_state.stmf_ilportlist; ilport; 5123 ilport = ilport->ilport_next) { 5124 if (ilport->ilport_standby == 1) { 5125 nports_standby++; 5126 } else { 5127 nports++; 5128 } 5129 } 5130 5131 /* The spec only allows for 255 ports to be reported per group */ 5132 nports = min(nports, 255); 5133 nports_standby = min(nports_standby, 255); 5134 sz = (nports * 4) + 12; 5135 if (nports_standby && ilu_alua) { 5136 sz += (nports_standby * 4) + 8; 5137 } 5138 asz = sz + sizeof (*xd) - 4; 5139 xd = (stmf_xfer_data_t *)kmem_zalloc(asz, KM_NOSLEEP); 5140 if (xd == NULL) { 5141 mutex_exit(&stmf_state.stmf_lock); 5142 return (NULL); 5143 } 5144 xd->alloc_size = asz; 5145 xd->size_left = sz; 5146 5147 p = xd->buf; 5148 5149 *((uint32_t *)p) = BE_32(sz - 4); 5150 p += 4; 5151 p[0] = 0x80; /* PREF */ 5152 p[1] = 5; /* AO_SUP, S_SUP */ 5153 if (stmf_state.stmf_alua_node == 1) { 5154 p[3] = 1; /* Group 1 */ 5155 } else { 5156 p[3] = 0; /* Group 0 */ 5157 } 5158 p[7] = nports & 0xff; 5159 p += 8; 5160 for (ilport = stmf_state.stmf_ilportlist; ilport; 5161 ilport = ilport->ilport_next) { 5162 if (ilport->ilport_standby == 1) { 5163 continue; 5164 } 5165 ((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid); 5166 p += 4; 5167 } 5168 if (nports_standby && ilu_alua) { 5169 p[0] = 0x02; /* Non PREF, Standby */ 5170 p[1] = 5; /* AO_SUP, S_SUP */ 5171 if (stmf_state.stmf_alua_node == 1) { 5172 p[3] = 0; /* Group 0 */ 5173 } else { 5174 p[3] = 1; /* Group 1 */ 5175 } 5176 p[7] = nports_standby & 0xff; 5177 p += 8; 5178 for (ilport = stmf_state.stmf_ilportlist; ilport; 5179 ilport = ilport->ilport_next) { 5180 if (ilport->ilport_standby == 0) { 5181 continue; 5182 } 5183 ((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid); 5184 p += 4; 5185 } 5186 } 5187 5188 mutex_exit(&stmf_state.stmf_lock); 5189 5190 return (xd); 5191 } 5192 5193 struct scsi_devid_desc * 5194 stmf_scsilib_get_devid_desc(uint16_t rtpid) 5195 { 5196 scsi_devid_desc_t *devid = NULL; 5197 stmf_i_local_port_t *ilport; 5198 5199 mutex_enter(&stmf_state.stmf_lock); 5200 5201 for (ilport = stmf_state.stmf_ilportlist; ilport; 5202 ilport = ilport->ilport_next) { 5203 if (ilport->ilport_rtpid == rtpid) { 5204 scsi_devid_desc_t *id = ilport->ilport_lport->lport_id; 5205 uint32_t id_sz = sizeof (scsi_devid_desc_t) - 1 + 5206 id->ident_length; 5207 devid = (scsi_devid_desc_t *)kmem_zalloc(id_sz, 5208 KM_NOSLEEP); 5209 if (devid != NULL) { 5210 bcopy(id, devid, id_sz); 5211 } 5212 break; 5213 } 5214 } 5215 5216 mutex_exit(&stmf_state.stmf_lock); 5217 return (devid); 5218 } 5219 5220 uint16_t 5221 stmf_scsilib_get_lport_rtid(struct scsi_devid_desc *devid) 5222 { 5223 stmf_i_local_port_t *ilport; 5224 scsi_devid_desc_t *id; 5225 uint16_t rtpid = 0; 5226 5227 mutex_enter(&stmf_state.stmf_lock); 5228 for (ilport = stmf_state.stmf_ilportlist; ilport; 5229 ilport = ilport->ilport_next) { 5230 id = ilport->ilport_lport->lport_id; 5231 if ((devid->ident_length == id->ident_length) && 5232 (memcmp(devid->ident, id->ident, id->ident_length) == 0)) { 5233 rtpid = ilport->ilport_rtpid; 5234 break; 5235 } 5236 } 5237 mutex_exit(&stmf_state.stmf_lock); 5238 return (rtpid); 5239 } 5240 5241 static uint16_t stmf_lu_id_gen_number = 0; 5242 5243 stmf_status_t 5244 stmf_scsilib_uniq_lu_id(uint32_t company_id, scsi_devid_desc_t *lu_id) 5245 { 5246 return (stmf_scsilib_uniq_lu_id2(company_id, 0, lu_id)); 5247 } 5248 5249 stmf_status_t 5250 stmf_scsilib_uniq_lu_id2(uint32_t company_id, uint32_t host_id, 5251 scsi_devid_desc_t *lu_id) 5252 { 5253 uint8_t *p; 5254 struct timeval32 timestamp32; 5255 uint32_t *t = (uint32_t *)×tamp32; 5256 struct ether_addr mac; 5257 uint8_t *e = (uint8_t *)&mac; 5258 int hid = (int)host_id; 5259 5260 if (company_id == COMPANY_ID_NONE) 5261 company_id = COMPANY_ID_SUN; 5262 5263 if (lu_id->ident_length != 0x10) 5264 return (STMF_INVALID_ARG); 5265 5266 p = (uint8_t *)lu_id; 5267 5268 atomic_add_16(&stmf_lu_id_gen_number, 1); 5269 5270 p[0] = 0xf1; p[1] = 3; p[2] = 0; p[3] = 0x10; 5271 p[4] = ((company_id >> 20) & 0xf) | 0x60; 5272 p[5] = (company_id >> 12) & 0xff; 5273 p[6] = (company_id >> 4) & 0xff; 5274 p[7] = (company_id << 4) & 0xf0; 5275 if (hid == 0 && !localetheraddr((struct ether_addr *)NULL, &mac)) { 5276 hid = BE_32((int)zone_get_hostid(NULL)); 5277 } 5278 if (hid != 0) { 5279 e[0] = (hid >> 24) & 0xff; 5280 e[1] = (hid >> 16) & 0xff; 5281 e[2] = (hid >> 8) & 0xff; 5282 e[3] = hid & 0xff; 5283 e[4] = e[5] = 0; 5284 } 5285 bcopy(e, p+8, 6); 5286 uniqtime32(×tamp32); 5287 *t = BE_32(*t); 5288 bcopy(t, p+14, 4); 5289 p[18] = (stmf_lu_id_gen_number >> 8) & 0xff; 5290 p[19] = stmf_lu_id_gen_number & 0xff; 5291 5292 return (STMF_SUCCESS); 5293 } 5294 5295 /* 5296 * saa is sense key, ASC, ASCQ 5297 */ 5298 void 5299 stmf_scsilib_send_status(scsi_task_t *task, uint8_t st, uint32_t saa) 5300 { 5301 uint8_t sd[18]; 5302 task->task_scsi_status = st; 5303 if (st == 2) { 5304 bzero(sd, 18); 5305 sd[0] = 0x70; 5306 sd[2] = (saa >> 16) & 0xf; 5307 sd[7] = 10; 5308 sd[12] = (saa >> 8) & 0xff; 5309 sd[13] = saa & 0xff; 5310 task->task_sense_data = sd; 5311 task->task_sense_length = 18; 5312 } else { 5313 task->task_sense_data = NULL; 5314 task->task_sense_length = 0; 5315 } 5316 (void) stmf_send_scsi_status(task, STMF_IOF_LU_DONE); 5317 } 5318 5319 uint32_t 5320 stmf_scsilib_prepare_vpd_page83(scsi_task_t *task, uint8_t *page, 5321 uint32_t page_len, uint8_t byte0, uint32_t vpd_mask) 5322 { 5323 uint8_t *p = NULL; 5324 uint8_t small_buf[32]; 5325 uint32_t sz = 0; 5326 uint32_t n = 4; 5327 uint32_t m = 0; 5328 uint32_t last_bit = 0; 5329 5330 if (page_len < 4) 5331 return (0); 5332 if (page_len > 65535) 5333 page_len = 65535; 5334 5335 page[0] = byte0; 5336 page[1] = 0x83; 5337 5338 /* CONSTCOND */ 5339 while (1) { 5340 m += sz; 5341 if (sz && (page_len > n)) { 5342 uint32_t copysz; 5343 copysz = page_len > (n + sz) ? sz : page_len - n; 5344 bcopy(p, page + n, copysz); 5345 n += copysz; 5346 } 5347 vpd_mask &= ~last_bit; 5348 if (vpd_mask == 0) 5349 break; 5350 5351 if (vpd_mask & STMF_VPD_LU_ID) { 5352 last_bit = STMF_VPD_LU_ID; 5353 sz = task->task_lu->lu_id->ident_length + 4; 5354 p = (uint8_t *)task->task_lu->lu_id; 5355 continue; 5356 } else if (vpd_mask & STMF_VPD_TARGET_ID) { 5357 last_bit = STMF_VPD_TARGET_ID; 5358 sz = task->task_lport->lport_id->ident_length + 4; 5359 p = (uint8_t *)task->task_lport->lport_id; 5360 continue; 5361 } else if (vpd_mask & STMF_VPD_TP_GROUP) { 5362 stmf_i_local_port_t *ilport; 5363 last_bit = STMF_VPD_TP_GROUP; 5364 p = small_buf; 5365 bzero(p, 8); 5366 p[0] = 1; 5367 p[1] = 0x15; 5368 p[3] = 4; 5369 ilport = (stmf_i_local_port_t *) 5370 task->task_lport->lport_stmf_private; 5371 if (ilport->ilport_rtpid > 255) { 5372 p[7] = 1; /* Group 1 */ 5373 } 5374 sz = 8; 5375 continue; 5376 } else if (vpd_mask & STMF_VPD_RELATIVE_TP_ID) { 5377 stmf_i_local_port_t *ilport; 5378 5379 last_bit = STMF_VPD_RELATIVE_TP_ID; 5380 p = small_buf; 5381 bzero(p, 8); 5382 p[0] = 1; 5383 p[1] = 0x14; 5384 p[3] = 4; 5385 ilport = (stmf_i_local_port_t *) 5386 task->task_lport->lport_stmf_private; 5387 p[6] = (ilport->ilport_rtpid >> 8) & 0xff; 5388 p[7] = ilport->ilport_rtpid & 0xff; 5389 sz = 8; 5390 continue; 5391 } else { 5392 cmn_err(CE_WARN, "Invalid vpd_mask"); 5393 break; 5394 } 5395 } 5396 5397 page[2] = (m >> 8) & 0xff; 5398 page[3] = m & 0xff; 5399 5400 return (n); 5401 } 5402 5403 void 5404 stmf_scsilib_handle_report_tpgs(scsi_task_t *task, stmf_data_buf_t *dbuf) 5405 { 5406 stmf_i_scsi_task_t *itask = 5407 (stmf_i_scsi_task_t *)task->task_stmf_private; 5408 stmf_i_lu_t *ilu = 5409 (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 5410 stmf_xfer_data_t *xd; 5411 uint32_t sz, minsz; 5412 5413 itask->itask_flags |= ITASK_DEFAULT_HANDLING; 5414 task->task_cmd_xfer_length = 5415 ((((uint32_t)task->task_cdb[6]) << 24) | 5416 (((uint32_t)task->task_cdb[7]) << 16) | 5417 (((uint32_t)task->task_cdb[8]) << 8) | 5418 ((uint32_t)task->task_cdb[9])); 5419 5420 if (task->task_additional_flags & 5421 TASK_AF_NO_EXPECTED_XFER_LENGTH) { 5422 task->task_expected_xfer_length = 5423 task->task_cmd_xfer_length; 5424 } 5425 5426 if (task->task_cmd_xfer_length == 0) { 5427 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 5428 return; 5429 } 5430 if (task->task_cmd_xfer_length < 4) { 5431 stmf_scsilib_send_status(task, STATUS_CHECK, 5432 STMF_SAA_INVALID_FIELD_IN_CDB); 5433 return; 5434 } 5435 5436 sz = min(task->task_expected_xfer_length, 5437 task->task_cmd_xfer_length); 5438 5439 xd = stmf_prepare_tpgs_data(ilu->ilu_alua); 5440 5441 if (xd == NULL) { 5442 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 5443 STMF_ALLOC_FAILURE, NULL); 5444 return; 5445 } 5446 5447 sz = min(sz, xd->size_left); 5448 xd->size_left = sz; 5449 minsz = min(512, sz); 5450 5451 if (dbuf == NULL) 5452 dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0); 5453 if (dbuf == NULL) { 5454 kmem_free(xd, xd->alloc_size); 5455 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 5456 STMF_ALLOC_FAILURE, NULL); 5457 return; 5458 } 5459 dbuf->db_lu_private = xd; 5460 stmf_xd_to_dbuf(dbuf); 5461 5462 dbuf->db_flags = DB_DIRECTION_TO_RPORT; 5463 (void) stmf_xfer_data(task, dbuf, 0); 5464 5465 } 5466 5467 void 5468 stmf_scsilib_handle_task_mgmt(scsi_task_t *task) 5469 { 5470 5471 switch (task->task_mgmt_function) { 5472 /* 5473 * For now we will abort all I/Os on the LU in case of ABORT_TASK_SET 5474 * and ABORT_TASK. But unlike LUN_RESET we will not reset LU state 5475 * in these cases. This needs to be changed to abort only the required 5476 * set. 5477 */ 5478 case TM_ABORT_TASK: 5479 case TM_ABORT_TASK_SET: 5480 case TM_CLEAR_TASK_SET: 5481 case TM_LUN_RESET: 5482 stmf_handle_lun_reset(task); 5483 /* issue the reset to the proxy node as well */ 5484 (void) stmf_proxy_scsi_cmd(task, NULL); 5485 return; 5486 case TM_TARGET_RESET: 5487 case TM_TARGET_COLD_RESET: 5488 case TM_TARGET_WARM_RESET: 5489 stmf_handle_target_reset(task); 5490 return; 5491 default: 5492 /* We dont support this task mgmt function */ 5493 stmf_scsilib_send_status(task, STATUS_CHECK, 5494 STMF_SAA_INVALID_FIELD_IN_CMD_IU); 5495 return; 5496 } 5497 } 5498 5499 void 5500 stmf_handle_lun_reset(scsi_task_t *task) 5501 { 5502 stmf_i_scsi_task_t *itask; 5503 stmf_i_lu_t *ilu; 5504 5505 itask = (stmf_i_scsi_task_t *)task->task_stmf_private; 5506 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 5507 5508 /* 5509 * To sync with target reset, grab this lock. The LU is not going 5510 * anywhere as there is atleast one task pending (this task). 5511 */ 5512 mutex_enter(&stmf_state.stmf_lock); 5513 5514 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 5515 mutex_exit(&stmf_state.stmf_lock); 5516 stmf_scsilib_send_status(task, STATUS_CHECK, 5517 STMF_SAA_OPERATION_IN_PROGRESS); 5518 return; 5519 } 5520 atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE); 5521 mutex_exit(&stmf_state.stmf_lock); 5522 5523 /* 5524 * Mark this task as the one causing LU reset so that we know who 5525 * was responsible for setting the ILU_RESET_ACTIVE. In case this 5526 * task itself gets aborted, we will clear ILU_RESET_ACTIVE. 5527 */ 5528 itask->itask_flags |= ITASK_DEFAULT_HANDLING | ITASK_CAUSING_LU_RESET; 5529 5530 /* Initiatiate abort on all commands on this LU except this one */ 5531 stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED, task->task_lu); 5532 5533 /* Start polling on this task */ 5534 if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT) 5535 != STMF_SUCCESS) { 5536 stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE, 5537 NULL); 5538 return; 5539 } 5540 } 5541 5542 void 5543 stmf_handle_target_reset(scsi_task_t *task) 5544 { 5545 stmf_i_scsi_task_t *itask; 5546 stmf_i_lu_t *ilu; 5547 stmf_i_scsi_session_t *iss; 5548 stmf_lun_map_t *lm; 5549 stmf_lun_map_ent_t *lm_ent; 5550 int i, lf; 5551 5552 itask = (stmf_i_scsi_task_t *)task->task_stmf_private; 5553 iss = (stmf_i_scsi_session_t *)task->task_session->ss_stmf_private; 5554 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 5555 5556 /* 5557 * To sync with LUN reset, grab this lock. The session is not going 5558 * anywhere as there is atleast one task pending (this task). 5559 */ 5560 mutex_enter(&stmf_state.stmf_lock); 5561 5562 /* Grab the session lock as a writer to prevent any changes in it */ 5563 rw_enter(iss->iss_lockp, RW_WRITER); 5564 5565 if (iss->iss_flags & ISS_RESET_ACTIVE) { 5566 rw_exit(iss->iss_lockp); 5567 mutex_exit(&stmf_state.stmf_lock); 5568 stmf_scsilib_send_status(task, STATUS_CHECK, 5569 STMF_SAA_OPERATION_IN_PROGRESS); 5570 return; 5571 } 5572 atomic_or_32(&iss->iss_flags, ISS_RESET_ACTIVE); 5573 5574 /* 5575 * Now go through each LUN in this session and make sure all of them 5576 * can be reset. 5577 */ 5578 lm = iss->iss_sm; 5579 for (i = 0, lf = 0; i < lm->lm_nentries; i++) { 5580 if (lm->lm_plus[i] == NULL) 5581 continue; 5582 lf++; 5583 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 5584 ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private); 5585 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 5586 atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE); 5587 rw_exit(iss->iss_lockp); 5588 mutex_exit(&stmf_state.stmf_lock); 5589 stmf_scsilib_send_status(task, STATUS_CHECK, 5590 STMF_SAA_OPERATION_IN_PROGRESS); 5591 return; 5592 } 5593 } 5594 if (lf == 0) { 5595 /* No luns in this session */ 5596 atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE); 5597 rw_exit(iss->iss_lockp); 5598 mutex_exit(&stmf_state.stmf_lock); 5599 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 5600 return; 5601 } 5602 5603 /* ok, start the damage */ 5604 itask->itask_flags |= ITASK_DEFAULT_HANDLING | 5605 ITASK_CAUSING_TARGET_RESET; 5606 for (i = 0; i < lm->lm_nentries; i++) { 5607 if (lm->lm_plus[i] == NULL) 5608 continue; 5609 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 5610 ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private); 5611 atomic_or_32(&ilu->ilu_flags, ILU_RESET_ACTIVE); 5612 } 5613 rw_exit(iss->iss_lockp); 5614 mutex_exit(&stmf_state.stmf_lock); 5615 5616 for (i = 0; i < lm->lm_nentries; i++) { 5617 if (lm->lm_plus[i] == NULL) 5618 continue; 5619 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 5620 stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED, 5621 lm_ent->ent_lu); 5622 } 5623 5624 /* Start polling on this task */ 5625 if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT) 5626 != STMF_SUCCESS) { 5627 stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE, 5628 NULL); 5629 return; 5630 } 5631 } 5632 5633 int 5634 stmf_handle_cmd_during_ic(stmf_i_scsi_task_t *itask) 5635 { 5636 scsi_task_t *task = itask->itask_task; 5637 stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *) 5638 task->task_session->ss_stmf_private; 5639 5640 rw_enter(iss->iss_lockp, RW_WRITER); 5641 if (((iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) == 0) || 5642 (task->task_cdb[0] == SCMD_INQUIRY)) { 5643 rw_exit(iss->iss_lockp); 5644 return (0); 5645 } 5646 atomic_and_32(&iss->iss_flags, 5647 ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS)); 5648 rw_exit(iss->iss_lockp); 5649 5650 if (task->task_cdb[0] == SCMD_REPORT_LUNS) { 5651 return (0); 5652 } 5653 stmf_scsilib_send_status(task, STATUS_CHECK, 5654 STMF_SAA_REPORT_LUN_DATA_HAS_CHANGED); 5655 return (1); 5656 } 5657 5658 void 5659 stmf_worker_init() 5660 { 5661 uint32_t i; 5662 5663 /* Make local copy of global tunables */ 5664 stmf_i_max_nworkers = stmf_max_nworkers; 5665 stmf_i_min_nworkers = stmf_min_nworkers; 5666 5667 ASSERT(stmf_workers == NULL); 5668 if (stmf_i_min_nworkers < 4) { 5669 stmf_i_min_nworkers = 4; 5670 } 5671 if (stmf_i_max_nworkers < stmf_i_min_nworkers) { 5672 stmf_i_max_nworkers = stmf_i_min_nworkers; 5673 } 5674 stmf_workers = (stmf_worker_t *)kmem_zalloc( 5675 sizeof (stmf_worker_t) * stmf_i_max_nworkers, KM_SLEEP); 5676 for (i = 0; i < stmf_i_max_nworkers; i++) { 5677 stmf_worker_t *w = &stmf_workers[i]; 5678 mutex_init(&w->worker_lock, NULL, MUTEX_DRIVER, NULL); 5679 cv_init(&w->worker_cv, NULL, CV_DRIVER, NULL); 5680 } 5681 stmf_worker_mgmt_delay = drv_usectohz(20 * 1000); 5682 stmf_workers_state = STMF_WORKERS_ENABLED; 5683 5684 /* Workers will be started by stmf_worker_mgmt() */ 5685 5686 /* Lets wait for atleast one worker to start */ 5687 while (stmf_nworkers_cur == 0) 5688 delay(drv_usectohz(20 * 1000)); 5689 stmf_worker_mgmt_delay = drv_usectohz(3 * 1000 * 1000); 5690 } 5691 5692 stmf_status_t 5693 stmf_worker_fini() 5694 { 5695 int i; 5696 clock_t sb; 5697 5698 if (stmf_workers_state == STMF_WORKERS_DISABLED) 5699 return (STMF_SUCCESS); 5700 ASSERT(stmf_workers); 5701 stmf_workers_state = STMF_WORKERS_DISABLED; 5702 stmf_worker_mgmt_delay = drv_usectohz(20 * 1000); 5703 cv_signal(&stmf_state.stmf_cv); 5704 5705 sb = ddi_get_lbolt() + drv_usectohz(10 * 1000 * 1000); 5706 /* Wait for all the threads to die */ 5707 while (stmf_nworkers_cur != 0) { 5708 if (ddi_get_lbolt() > sb) { 5709 stmf_workers_state = STMF_WORKERS_ENABLED; 5710 return (STMF_BUSY); 5711 } 5712 delay(drv_usectohz(100 * 1000)); 5713 } 5714 for (i = 0; i < stmf_i_max_nworkers; i++) { 5715 stmf_worker_t *w = &stmf_workers[i]; 5716 mutex_destroy(&w->worker_lock); 5717 cv_destroy(&w->worker_cv); 5718 } 5719 kmem_free(stmf_workers, sizeof (stmf_worker_t) * stmf_i_max_nworkers); 5720 stmf_workers = NULL; 5721 5722 return (STMF_SUCCESS); 5723 } 5724 5725 void 5726 stmf_worker_task(void *arg) 5727 { 5728 stmf_worker_t *w; 5729 stmf_i_scsi_session_t *iss; 5730 scsi_task_t *task; 5731 stmf_i_scsi_task_t *itask; 5732 stmf_data_buf_t *dbuf; 5733 stmf_lu_t *lu; 5734 clock_t wait_timer = 0; 5735 clock_t wait_ticks, wait_delta = 0; 5736 uint32_t old, new; 5737 uint8_t curcmd; 5738 uint8_t abort_free; 5739 uint8_t wait_queue; 5740 uint8_t dec_qdepth; 5741 5742 w = (stmf_worker_t *)arg; 5743 wait_ticks = drv_usectohz(10000); 5744 5745 mutex_enter(&w->worker_lock); 5746 w->worker_flags |= STMF_WORKER_STARTED | STMF_WORKER_ACTIVE; 5747 stmf_worker_loop:; 5748 if ((w->worker_ref_count == 0) && 5749 (w->worker_flags & STMF_WORKER_TERMINATE)) { 5750 w->worker_flags &= ~(STMF_WORKER_STARTED | 5751 STMF_WORKER_ACTIVE | STMF_WORKER_TERMINATE); 5752 w->worker_tid = NULL; 5753 mutex_exit(&w->worker_lock); 5754 thread_exit(); 5755 } 5756 /* CONSTCOND */ 5757 while (1) { 5758 dec_qdepth = 0; 5759 if (wait_timer && (ddi_get_lbolt() >= wait_timer)) { 5760 wait_timer = 0; 5761 wait_delta = 0; 5762 if (w->worker_wait_head) { 5763 ASSERT(w->worker_wait_tail); 5764 if (w->worker_task_head == NULL) 5765 w->worker_task_head = 5766 w->worker_wait_head; 5767 else 5768 w->worker_task_tail->itask_worker_next = 5769 w->worker_wait_head; 5770 w->worker_task_tail = w->worker_wait_tail; 5771 w->worker_wait_head = w->worker_wait_tail = 5772 NULL; 5773 } 5774 } 5775 if ((itask = w->worker_task_head) == NULL) { 5776 break; 5777 } 5778 task = itask->itask_task; 5779 w->worker_task_head = itask->itask_worker_next; 5780 if (w->worker_task_head == NULL) 5781 w->worker_task_tail = NULL; 5782 5783 wait_queue = 0; 5784 abort_free = 0; 5785 if (itask->itask_ncmds > 0) { 5786 curcmd = itask->itask_cmd_stack[itask->itask_ncmds - 1]; 5787 } else { 5788 ASSERT(itask->itask_flags & ITASK_BEING_ABORTED); 5789 } 5790 do { 5791 old = itask->itask_flags; 5792 if (old & ITASK_BEING_ABORTED) { 5793 itask->itask_ncmds = 1; 5794 curcmd = itask->itask_cmd_stack[0] = 5795 ITASK_CMD_ABORT; 5796 goto out_itask_flag_loop; 5797 } else if ((curcmd & ITASK_CMD_MASK) == 5798 ITASK_CMD_NEW_TASK) { 5799 /* 5800 * set ITASK_KSTAT_IN_RUNQ, this flag 5801 * will not reset until task completed 5802 */ 5803 new = old | ITASK_KNOWN_TO_LU | 5804 ITASK_KSTAT_IN_RUNQ; 5805 } else { 5806 goto out_itask_flag_loop; 5807 } 5808 } while (atomic_cas_32(&itask->itask_flags, old, new) != old); 5809 5810 out_itask_flag_loop: 5811 5812 /* 5813 * Decide if this task needs to go to a queue and/or if 5814 * we can decrement the itask_cmd_stack. 5815 */ 5816 if (curcmd == ITASK_CMD_ABORT) { 5817 if (itask->itask_flags & (ITASK_KNOWN_TO_LU | 5818 ITASK_KNOWN_TO_TGT_PORT)) { 5819 wait_queue = 1; 5820 } else { 5821 abort_free = 1; 5822 } 5823 } else if ((curcmd & ITASK_CMD_POLL) && 5824 (itask->itask_poll_timeout > ddi_get_lbolt())) { 5825 wait_queue = 1; 5826 } 5827 5828 if (wait_queue) { 5829 itask->itask_worker_next = NULL; 5830 if (w->worker_wait_tail) { 5831 w->worker_wait_tail->itask_worker_next = itask; 5832 } else { 5833 w->worker_wait_head = itask; 5834 } 5835 w->worker_wait_tail = itask; 5836 if (wait_timer == 0) { 5837 wait_timer = ddi_get_lbolt() + wait_ticks; 5838 wait_delta = wait_ticks; 5839 } 5840 } else if ((--(itask->itask_ncmds)) != 0) { 5841 itask->itask_worker_next = NULL; 5842 if (w->worker_task_tail) { 5843 w->worker_task_tail->itask_worker_next = itask; 5844 } else { 5845 w->worker_task_head = itask; 5846 } 5847 w->worker_task_tail = itask; 5848 } else { 5849 atomic_and_32(&itask->itask_flags, 5850 ~ITASK_IN_WORKER_QUEUE); 5851 /* 5852 * This is where the queue depth should go down by 5853 * one but we delay that on purpose to account for 5854 * the call into the provider. The actual decrement 5855 * happens after the worker has done its job. 5856 */ 5857 dec_qdepth = 1; 5858 } 5859 5860 /* We made it here means we are going to call LU */ 5861 if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0) 5862 lu = task->task_lu; 5863 else 5864 lu = dlun0; 5865 dbuf = itask->itask_dbufs[ITASK_CMD_BUF_NDX(curcmd)]; 5866 mutex_exit(&w->worker_lock); 5867 curcmd &= ITASK_CMD_MASK; 5868 switch (curcmd) { 5869 case ITASK_CMD_NEW_TASK: 5870 iss = (stmf_i_scsi_session_t *) 5871 task->task_session->ss_stmf_private; 5872 stmf_update_kstat_lu_q(task, kstat_waitq_to_runq); 5873 stmf_update_kstat_lport_q(task, kstat_waitq_to_runq); 5874 if (iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) { 5875 if (stmf_handle_cmd_during_ic(itask)) 5876 break; 5877 } 5878 #ifdef DEBUG 5879 if (stmf_drop_task_counter > 0) { 5880 if (atomic_add_32_nv( 5881 (uint32_t *)&stmf_drop_task_counter, 5882 -1) == 1) { 5883 break; 5884 } 5885 } 5886 #endif 5887 DTRACE_PROBE1(scsi__task__start, scsi_task_t *, task); 5888 lu->lu_new_task(task, dbuf); 5889 break; 5890 case ITASK_CMD_DATA_XFER_DONE: 5891 lu->lu_dbuf_xfer_done(task, dbuf); 5892 break; 5893 case ITASK_CMD_STATUS_DONE: 5894 lu->lu_send_status_done(task); 5895 break; 5896 case ITASK_CMD_ABORT: 5897 if (abort_free) { 5898 stmf_task_free(task); 5899 } else { 5900 stmf_do_task_abort(task); 5901 } 5902 break; 5903 case ITASK_CMD_POLL_LU: 5904 if (!wait_queue) { 5905 lu->lu_task_poll(task); 5906 } 5907 break; 5908 case ITASK_CMD_POLL_LPORT: 5909 if (!wait_queue) 5910 task->task_lport->lport_task_poll(task); 5911 break; 5912 case ITASK_CMD_SEND_STATUS: 5913 /* case ITASK_CMD_XFER_DATA: */ 5914 break; 5915 } 5916 mutex_enter(&w->worker_lock); 5917 if (dec_qdepth) { 5918 w->worker_queue_depth--; 5919 } 5920 } 5921 if ((w->worker_flags & STMF_WORKER_TERMINATE) && (wait_timer == 0)) { 5922 if (w->worker_ref_count == 0) 5923 goto stmf_worker_loop; 5924 else { 5925 wait_timer = ddi_get_lbolt() + 1; 5926 wait_delta = 1; 5927 } 5928 } 5929 w->worker_flags &= ~STMF_WORKER_ACTIVE; 5930 if (wait_timer) { 5931 (void) cv_reltimedwait(&w->worker_cv, &w->worker_lock, 5932 wait_delta, TR_CLOCK_TICK); 5933 } else { 5934 cv_wait(&w->worker_cv, &w->worker_lock); 5935 } 5936 w->worker_flags |= STMF_WORKER_ACTIVE; 5937 goto stmf_worker_loop; 5938 } 5939 5940 void 5941 stmf_worker_mgmt() 5942 { 5943 int i; 5944 int workers_needed; 5945 uint32_t qd; 5946 clock_t tps, d = 0; 5947 uint32_t cur_max_ntasks = 0; 5948 stmf_worker_t *w; 5949 5950 /* Check if we are trying to increase the # of threads */ 5951 for (i = stmf_nworkers_cur; i < stmf_nworkers_needed; i++) { 5952 if (stmf_workers[i].worker_flags & STMF_WORKER_STARTED) { 5953 stmf_nworkers_cur++; 5954 stmf_nworkers_accepting_cmds++; 5955 } else { 5956 /* Wait for transition to complete */ 5957 return; 5958 } 5959 } 5960 /* Check if we are trying to decrease the # of workers */ 5961 for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) { 5962 if ((stmf_workers[i].worker_flags & STMF_WORKER_STARTED) == 0) { 5963 stmf_nworkers_cur--; 5964 /* 5965 * stmf_nworkers_accepting_cmds has already been 5966 * updated by the request to reduce the # of workers. 5967 */ 5968 } else { 5969 /* Wait for transition to complete */ 5970 return; 5971 } 5972 } 5973 /* Check if we are being asked to quit */ 5974 if (stmf_workers_state != STMF_WORKERS_ENABLED) { 5975 if (stmf_nworkers_cur) { 5976 workers_needed = 0; 5977 goto worker_mgmt_trigger_change; 5978 } 5979 return; 5980 } 5981 /* Check if we are starting */ 5982 if (stmf_nworkers_cur < stmf_i_min_nworkers) { 5983 workers_needed = stmf_i_min_nworkers; 5984 goto worker_mgmt_trigger_change; 5985 } 5986 5987 tps = drv_usectohz(1 * 1000 * 1000); 5988 if ((stmf_wm_last != 0) && 5989 ((d = ddi_get_lbolt() - stmf_wm_last) > tps)) { 5990 qd = 0; 5991 for (i = 0; i < stmf_nworkers_accepting_cmds; i++) { 5992 qd += stmf_workers[i].worker_max_qdepth_pu; 5993 stmf_workers[i].worker_max_qdepth_pu = 0; 5994 if (stmf_workers[i].worker_max_sys_qdepth_pu > 5995 cur_max_ntasks) { 5996 cur_max_ntasks = 5997 stmf_workers[i].worker_max_sys_qdepth_pu; 5998 } 5999 stmf_workers[i].worker_max_sys_qdepth_pu = 0; 6000 } 6001 } 6002 stmf_wm_last = ddi_get_lbolt(); 6003 if (d <= tps) { 6004 /* still ramping up */ 6005 return; 6006 } 6007 /* max qdepth cannot be more than max tasks */ 6008 if (qd > cur_max_ntasks) 6009 qd = cur_max_ntasks; 6010 6011 /* See if we have more workers */ 6012 if (qd < stmf_nworkers_accepting_cmds) { 6013 /* 6014 * Since we dont reduce the worker count right away, monitor 6015 * the highest load during the scale_down_delay. 6016 */ 6017 if (qd > stmf_worker_scale_down_qd) 6018 stmf_worker_scale_down_qd = qd; 6019 if (stmf_worker_scale_down_timer == 0) { 6020 stmf_worker_scale_down_timer = ddi_get_lbolt() + 6021 drv_usectohz(stmf_worker_scale_down_delay * 6022 1000 * 1000); 6023 return; 6024 } 6025 if (ddi_get_lbolt() < stmf_worker_scale_down_timer) { 6026 return; 6027 } 6028 /* Its time to reduce the workers */ 6029 if (stmf_worker_scale_down_qd < stmf_i_min_nworkers) 6030 stmf_worker_scale_down_qd = stmf_i_min_nworkers; 6031 if (stmf_worker_scale_down_qd > stmf_i_max_nworkers) 6032 stmf_worker_scale_down_qd = stmf_i_max_nworkers; 6033 if (stmf_worker_scale_down_qd == stmf_nworkers_cur) 6034 return; 6035 workers_needed = stmf_worker_scale_down_qd; 6036 stmf_worker_scale_down_qd = 0; 6037 goto worker_mgmt_trigger_change; 6038 } 6039 stmf_worker_scale_down_qd = 0; 6040 stmf_worker_scale_down_timer = 0; 6041 if (qd > stmf_i_max_nworkers) 6042 qd = stmf_i_max_nworkers; 6043 if (qd < stmf_i_min_nworkers) 6044 qd = stmf_i_min_nworkers; 6045 if (qd == stmf_nworkers_cur) 6046 return; 6047 workers_needed = qd; 6048 goto worker_mgmt_trigger_change; 6049 6050 /* NOTREACHED */ 6051 return; 6052 6053 worker_mgmt_trigger_change: 6054 ASSERT(workers_needed != stmf_nworkers_cur); 6055 if (workers_needed > stmf_nworkers_cur) { 6056 stmf_nworkers_needed = workers_needed; 6057 for (i = stmf_nworkers_cur; i < workers_needed; i++) { 6058 w = &stmf_workers[i]; 6059 w->worker_tid = thread_create(NULL, 0, stmf_worker_task, 6060 (void *)&stmf_workers[i], 0, &p0, TS_RUN, 6061 minclsyspri); 6062 } 6063 return; 6064 } 6065 /* At this point we know that we are decreasing the # of workers */ 6066 stmf_nworkers_accepting_cmds = workers_needed; 6067 stmf_nworkers_needed = workers_needed; 6068 /* Signal the workers that its time to quit */ 6069 for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) { 6070 w = &stmf_workers[i]; 6071 ASSERT(w && (w->worker_flags & STMF_WORKER_STARTED)); 6072 mutex_enter(&w->worker_lock); 6073 w->worker_flags |= STMF_WORKER_TERMINATE; 6074 if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) 6075 cv_signal(&w->worker_cv); 6076 mutex_exit(&w->worker_lock); 6077 } 6078 } 6079 6080 /* 6081 * Fills out a dbuf from stmf_xfer_data_t (contained in the db_lu_private). 6082 * If all the data has been filled out, frees the xd and makes 6083 * db_lu_private NULL. 6084 */ 6085 void 6086 stmf_xd_to_dbuf(stmf_data_buf_t *dbuf) 6087 { 6088 stmf_xfer_data_t *xd; 6089 uint8_t *p; 6090 int i; 6091 uint32_t s; 6092 6093 xd = (stmf_xfer_data_t *)dbuf->db_lu_private; 6094 dbuf->db_data_size = 0; 6095 dbuf->db_relative_offset = xd->size_done; 6096 for (i = 0; i < dbuf->db_sglist_length; i++) { 6097 s = min(xd->size_left, dbuf->db_sglist[i].seg_length); 6098 p = &xd->buf[xd->size_done]; 6099 bcopy(p, dbuf->db_sglist[i].seg_addr, s); 6100 xd->size_left -= s; 6101 xd->size_done += s; 6102 dbuf->db_data_size += s; 6103 if (xd->size_left == 0) { 6104 kmem_free(xd, xd->alloc_size); 6105 dbuf->db_lu_private = NULL; 6106 return; 6107 } 6108 } 6109 } 6110 6111 /* ARGSUSED */ 6112 stmf_status_t 6113 stmf_dlun0_task_alloc(scsi_task_t *task) 6114 { 6115 return (STMF_SUCCESS); 6116 } 6117 6118 void 6119 stmf_dlun0_new_task(scsi_task_t *task, stmf_data_buf_t *dbuf) 6120 { 6121 uint8_t *cdbp = (uint8_t *)&task->task_cdb[0]; 6122 stmf_i_scsi_session_t *iss; 6123 uint32_t sz, minsz; 6124 uint8_t *p; 6125 stmf_xfer_data_t *xd; 6126 uint8_t inq_page_length = 31; 6127 6128 if (task->task_mgmt_function) { 6129 stmf_scsilib_handle_task_mgmt(task); 6130 return; 6131 } 6132 6133 switch (cdbp[0]) { 6134 case SCMD_INQUIRY: 6135 /* 6136 * Basic protocol checks. In addition, only reply to 6137 * standard inquiry. Otherwise, the LU provider needs 6138 * to respond. 6139 */ 6140 6141 if (cdbp[2] || (cdbp[1] & 1) || cdbp[5]) { 6142 stmf_scsilib_send_status(task, STATUS_CHECK, 6143 STMF_SAA_INVALID_FIELD_IN_CDB); 6144 return; 6145 } 6146 6147 task->task_cmd_xfer_length = 6148 (((uint32_t)cdbp[3]) << 8) | cdbp[4]; 6149 6150 if (task->task_additional_flags & 6151 TASK_AF_NO_EXPECTED_XFER_LENGTH) { 6152 task->task_expected_xfer_length = 6153 task->task_cmd_xfer_length; 6154 } 6155 6156 sz = min(task->task_expected_xfer_length, 6157 min(36, task->task_cmd_xfer_length)); 6158 minsz = 36; 6159 6160 if (sz == 0) { 6161 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 6162 return; 6163 } 6164 6165 if (dbuf && (dbuf->db_sglist[0].seg_length < 36)) { 6166 /* 6167 * Ignore any preallocated dbuf if the size is less 6168 * than 36. It will be freed during the task_free. 6169 */ 6170 dbuf = NULL; 6171 } 6172 if (dbuf == NULL) 6173 dbuf = stmf_alloc_dbuf(task, minsz, &minsz, 0); 6174 if ((dbuf == NULL) || (dbuf->db_sglist[0].seg_length < sz)) { 6175 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6176 STMF_ALLOC_FAILURE, NULL); 6177 return; 6178 } 6179 dbuf->db_lu_private = NULL; 6180 6181 p = dbuf->db_sglist[0].seg_addr; 6182 6183 /* 6184 * Standard inquiry handling only. 6185 */ 6186 6187 bzero(p, inq_page_length + 5); 6188 6189 p[0] = DPQ_SUPPORTED | DTYPE_UNKNOWN; 6190 p[2] = 5; 6191 p[3] = 0x12; 6192 p[4] = inq_page_length; 6193 p[6] = 0x80; 6194 6195 (void) strncpy((char *)p+8, "SUN ", 8); 6196 (void) strncpy((char *)p+16, "COMSTAR ", 16); 6197 (void) strncpy((char *)p+32, "1.0 ", 4); 6198 6199 dbuf->db_data_size = sz; 6200 dbuf->db_relative_offset = 0; 6201 dbuf->db_flags = DB_DIRECTION_TO_RPORT; 6202 (void) stmf_xfer_data(task, dbuf, 0); 6203 6204 return; 6205 6206 case SCMD_REPORT_LUNS: 6207 task->task_cmd_xfer_length = 6208 ((((uint32_t)task->task_cdb[6]) << 24) | 6209 (((uint32_t)task->task_cdb[7]) << 16) | 6210 (((uint32_t)task->task_cdb[8]) << 8) | 6211 ((uint32_t)task->task_cdb[9])); 6212 6213 if (task->task_additional_flags & 6214 TASK_AF_NO_EXPECTED_XFER_LENGTH) { 6215 task->task_expected_xfer_length = 6216 task->task_cmd_xfer_length; 6217 } 6218 6219 sz = min(task->task_expected_xfer_length, 6220 task->task_cmd_xfer_length); 6221 6222 if (sz < 16) { 6223 stmf_scsilib_send_status(task, STATUS_CHECK, 6224 STMF_SAA_INVALID_FIELD_IN_CDB); 6225 return; 6226 } 6227 6228 iss = (stmf_i_scsi_session_t *) 6229 task->task_session->ss_stmf_private; 6230 rw_enter(iss->iss_lockp, RW_WRITER); 6231 xd = stmf_session_prepare_report_lun_data(iss->iss_sm); 6232 rw_exit(iss->iss_lockp); 6233 6234 if (xd == NULL) { 6235 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6236 STMF_ALLOC_FAILURE, NULL); 6237 return; 6238 } 6239 6240 sz = min(sz, xd->size_left); 6241 xd->size_left = sz; 6242 minsz = min(512, sz); 6243 6244 if (dbuf == NULL) 6245 dbuf = stmf_alloc_dbuf(task, sz, &minsz, 0); 6246 if (dbuf == NULL) { 6247 kmem_free(xd, xd->alloc_size); 6248 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6249 STMF_ALLOC_FAILURE, NULL); 6250 return; 6251 } 6252 dbuf->db_lu_private = xd; 6253 stmf_xd_to_dbuf(dbuf); 6254 6255 atomic_and_32(&iss->iss_flags, 6256 ~(ISS_LUN_INVENTORY_CHANGED | ISS_GOT_INITIAL_LUNS)); 6257 dbuf->db_flags = DB_DIRECTION_TO_RPORT; 6258 (void) stmf_xfer_data(task, dbuf, 0); 6259 return; 6260 } 6261 6262 stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE); 6263 } 6264 6265 void 6266 stmf_dlun0_dbuf_done(scsi_task_t *task, stmf_data_buf_t *dbuf) 6267 { 6268 stmf_i_scsi_task_t *itask = 6269 (stmf_i_scsi_task_t *)task->task_stmf_private; 6270 6271 if (dbuf->db_xfer_status != STMF_SUCCESS) { 6272 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6273 dbuf->db_xfer_status, NULL); 6274 return; 6275 } 6276 task->task_nbytes_transferred = dbuf->db_data_size; 6277 if (dbuf->db_lu_private) { 6278 /* There is more */ 6279 stmf_xd_to_dbuf(dbuf); 6280 (void) stmf_xfer_data(task, dbuf, 0); 6281 return; 6282 } 6283 /* 6284 * If this is a proxy task, it will need to be completed from the 6285 * proxy port provider. This message lets pppt know that the xfer 6286 * is complete. When we receive the status from pppt, we will 6287 * then relay that status back to the lport. 6288 */ 6289 if (itask->itask_flags & ITASK_PROXY_TASK) { 6290 stmf_ic_msg_t *ic_xfer_done_msg = NULL; 6291 stmf_status_t ic_ret = STMF_FAILURE; 6292 uint64_t session_msg_id; 6293 mutex_enter(&stmf_state.stmf_lock); 6294 session_msg_id = stmf_proxy_msg_id++; 6295 mutex_exit(&stmf_state.stmf_lock); 6296 /* send xfer done status to pppt */ 6297 ic_xfer_done_msg = ic_scsi_data_xfer_done_msg_alloc( 6298 itask->itask_proxy_msg_id, 6299 task->task_session->ss_session_id, 6300 STMF_SUCCESS, session_msg_id); 6301 if (ic_xfer_done_msg) { 6302 ic_ret = ic_tx_msg(ic_xfer_done_msg); 6303 if (ic_ret != STMF_IC_MSG_SUCCESS) { 6304 cmn_err(CE_WARN, "unable to xmit session msg"); 6305 } 6306 } 6307 /* task will be completed from pppt */ 6308 return; 6309 } 6310 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 6311 } 6312 6313 /* ARGSUSED */ 6314 void 6315 stmf_dlun0_status_done(scsi_task_t *task) 6316 { 6317 } 6318 6319 /* ARGSUSED */ 6320 void 6321 stmf_dlun0_task_free(scsi_task_t *task) 6322 { 6323 } 6324 6325 /* ARGSUSED */ 6326 stmf_status_t 6327 stmf_dlun0_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags) 6328 { 6329 scsi_task_t *task = (scsi_task_t *)arg; 6330 stmf_i_scsi_task_t *itask = 6331 (stmf_i_scsi_task_t *)task->task_stmf_private; 6332 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private; 6333 int i; 6334 uint8_t map; 6335 6336 if ((task->task_mgmt_function) && (itask->itask_flags & 6337 (ITASK_CAUSING_LU_RESET | ITASK_CAUSING_TARGET_RESET))) { 6338 switch (task->task_mgmt_function) { 6339 case TM_ABORT_TASK: 6340 case TM_ABORT_TASK_SET: 6341 case TM_CLEAR_TASK_SET: 6342 case TM_LUN_RESET: 6343 atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE); 6344 break; 6345 case TM_TARGET_RESET: 6346 case TM_TARGET_COLD_RESET: 6347 case TM_TARGET_WARM_RESET: 6348 stmf_abort_target_reset(task); 6349 break; 6350 } 6351 return (STMF_ABORT_SUCCESS); 6352 } 6353 6354 /* 6355 * OK so its not a task mgmt. Make sure we free any xd sitting 6356 * inside any dbuf. 6357 */ 6358 if ((map = itask->itask_allocated_buf_map) != 0) { 6359 for (i = 0; i < 4; i++) { 6360 if ((map & 1) && 6361 ((itask->itask_dbufs[i])->db_lu_private)) { 6362 stmf_xfer_data_t *xd; 6363 stmf_data_buf_t *dbuf; 6364 6365 dbuf = itask->itask_dbufs[i]; 6366 xd = (stmf_xfer_data_t *)dbuf->db_lu_private; 6367 dbuf->db_lu_private = NULL; 6368 kmem_free(xd, xd->alloc_size); 6369 } 6370 map >>= 1; 6371 } 6372 } 6373 return (STMF_ABORT_SUCCESS); 6374 } 6375 6376 void 6377 stmf_dlun0_task_poll(struct scsi_task *task) 6378 { 6379 /* Right now we only do this for handling task management functions */ 6380 ASSERT(task->task_mgmt_function); 6381 6382 switch (task->task_mgmt_function) { 6383 case TM_ABORT_TASK: 6384 case TM_ABORT_TASK_SET: 6385 case TM_CLEAR_TASK_SET: 6386 case TM_LUN_RESET: 6387 (void) stmf_lun_reset_poll(task->task_lu, task, 0); 6388 return; 6389 case TM_TARGET_RESET: 6390 case TM_TARGET_COLD_RESET: 6391 case TM_TARGET_WARM_RESET: 6392 stmf_target_reset_poll(task); 6393 return; 6394 } 6395 } 6396 6397 /* ARGSUSED */ 6398 void 6399 stmf_dlun0_ctl(struct stmf_lu *lu, int cmd, void *arg) 6400 { 6401 /* This function will never be called */ 6402 cmn_err(CE_WARN, "stmf_dlun0_ctl called with cmd %x", cmd); 6403 } 6404 6405 void 6406 stmf_dlun_init() 6407 { 6408 stmf_i_lu_t *ilu; 6409 6410 dlun0 = stmf_alloc(STMF_STRUCT_STMF_LU, 0, 0); 6411 dlun0->lu_task_alloc = stmf_dlun0_task_alloc; 6412 dlun0->lu_new_task = stmf_dlun0_new_task; 6413 dlun0->lu_dbuf_xfer_done = stmf_dlun0_dbuf_done; 6414 dlun0->lu_send_status_done = stmf_dlun0_status_done; 6415 dlun0->lu_task_free = stmf_dlun0_task_free; 6416 dlun0->lu_abort = stmf_dlun0_abort; 6417 dlun0->lu_task_poll = stmf_dlun0_task_poll; 6418 dlun0->lu_ctl = stmf_dlun0_ctl; 6419 6420 ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private; 6421 ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1; 6422 } 6423 6424 stmf_status_t 6425 stmf_dlun_fini() 6426 { 6427 stmf_i_lu_t *ilu; 6428 6429 ilu = (stmf_i_lu_t *)dlun0->lu_stmf_private; 6430 6431 ASSERT(ilu->ilu_ntasks == ilu->ilu_ntasks_free); 6432 if (ilu->ilu_ntasks) { 6433 stmf_i_scsi_task_t *itask, *nitask; 6434 6435 nitask = ilu->ilu_tasks; 6436 do { 6437 itask = nitask; 6438 nitask = itask->itask_lu_next; 6439 dlun0->lu_task_free(itask->itask_task); 6440 stmf_free(itask->itask_task); 6441 } while (nitask != NULL); 6442 6443 } 6444 stmf_free(dlun0); 6445 return (STMF_SUCCESS); 6446 } 6447 6448 void 6449 stmf_abort_target_reset(scsi_task_t *task) 6450 { 6451 stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *) 6452 task->task_session->ss_stmf_private; 6453 stmf_lun_map_t *lm; 6454 stmf_lun_map_ent_t *lm_ent; 6455 stmf_i_lu_t *ilu; 6456 int i; 6457 6458 ASSERT(iss->iss_flags & ISS_RESET_ACTIVE); 6459 6460 rw_enter(iss->iss_lockp, RW_READER); 6461 lm = iss->iss_sm; 6462 for (i = 0; i < lm->lm_nentries; i++) { 6463 if (lm->lm_plus[i] == NULL) 6464 continue; 6465 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 6466 ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private; 6467 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 6468 atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE); 6469 } 6470 } 6471 atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE); 6472 rw_exit(iss->iss_lockp); 6473 } 6474 6475 /* 6476 * The return value is only used by function managing target reset. 6477 */ 6478 stmf_status_t 6479 stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task, int target_reset) 6480 { 6481 stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 6482 int ntasks_pending; 6483 6484 ntasks_pending = ilu->ilu_ntasks - ilu->ilu_ntasks_free; 6485 /* 6486 * This function is also used during Target reset. The idea is that 6487 * once all the commands are aborted, call the LU's reset entry 6488 * point (abort entry point with a reset flag). But if this Task 6489 * mgmt is running on this LU then all the tasks cannot be aborted. 6490 * one task (this task) will still be running which is OK. 6491 */ 6492 if ((ntasks_pending == 0) || ((task->task_lu == lu) && 6493 (ntasks_pending == 1))) { 6494 stmf_status_t ret; 6495 6496 if ((task->task_mgmt_function == TM_LUN_RESET) || 6497 (task->task_mgmt_function == TM_TARGET_RESET) || 6498 (task->task_mgmt_function == TM_TARGET_WARM_RESET) || 6499 (task->task_mgmt_function == TM_TARGET_COLD_RESET)) { 6500 ret = lu->lu_abort(lu, STMF_LU_RESET_STATE, task, 0); 6501 } else { 6502 ret = STMF_SUCCESS; 6503 } 6504 if (ret == STMF_SUCCESS) { 6505 atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE); 6506 } 6507 if (target_reset) { 6508 return (ret); 6509 } 6510 if (ret == STMF_SUCCESS) { 6511 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 6512 return (ret); 6513 } 6514 if (ret != STMF_BUSY) { 6515 stmf_abort(STMF_QUEUE_TASK_ABORT, task, ret, NULL); 6516 return (ret); 6517 } 6518 } 6519 6520 if (target_reset) { 6521 /* Tell target reset polling code that we are not done */ 6522 return (STMF_BUSY); 6523 } 6524 6525 if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT) 6526 != STMF_SUCCESS) { 6527 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6528 STMF_ALLOC_FAILURE, NULL); 6529 return (STMF_SUCCESS); 6530 } 6531 6532 return (STMF_SUCCESS); 6533 } 6534 6535 void 6536 stmf_target_reset_poll(struct scsi_task *task) 6537 { 6538 stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *) 6539 task->task_session->ss_stmf_private; 6540 stmf_lun_map_t *lm; 6541 stmf_lun_map_ent_t *lm_ent; 6542 stmf_i_lu_t *ilu; 6543 stmf_status_t ret; 6544 int i; 6545 int not_done = 0; 6546 6547 ASSERT(iss->iss_flags & ISS_RESET_ACTIVE); 6548 6549 rw_enter(iss->iss_lockp, RW_READER); 6550 lm = iss->iss_sm; 6551 for (i = 0; i < lm->lm_nentries; i++) { 6552 if (lm->lm_plus[i] == NULL) 6553 continue; 6554 lm_ent = (stmf_lun_map_ent_t *)lm->lm_plus[i]; 6555 ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private; 6556 if (ilu->ilu_flags & ILU_RESET_ACTIVE) { 6557 rw_exit(iss->iss_lockp); 6558 ret = stmf_lun_reset_poll(lm_ent->ent_lu, task, 1); 6559 rw_enter(iss->iss_lockp, RW_READER); 6560 if (ret == STMF_SUCCESS) 6561 continue; 6562 not_done = 1; 6563 if (ret != STMF_BUSY) { 6564 rw_exit(iss->iss_lockp); 6565 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6566 STMF_ABORTED, NULL); 6567 return; 6568 } 6569 } 6570 } 6571 rw_exit(iss->iss_lockp); 6572 6573 if (not_done) { 6574 if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT) 6575 != STMF_SUCCESS) { 6576 stmf_abort(STMF_QUEUE_TASK_ABORT, task, 6577 STMF_ALLOC_FAILURE, NULL); 6578 return; 6579 } 6580 return; 6581 } 6582 6583 atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE); 6584 6585 stmf_scsilib_send_status(task, STATUS_GOOD, 0); 6586 } 6587 6588 stmf_status_t 6589 stmf_lu_add_event(stmf_lu_t *lu, int eventid) 6590 { 6591 stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 6592 6593 if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) { 6594 return (STMF_INVALID_ARG); 6595 } 6596 6597 STMF_EVENT_ADD(ilu->ilu_event_hdl, eventid); 6598 return (STMF_SUCCESS); 6599 } 6600 6601 stmf_status_t 6602 stmf_lu_remove_event(stmf_lu_t *lu, int eventid) 6603 { 6604 stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 6605 6606 if (eventid == STMF_EVENT_ALL) { 6607 STMF_EVENT_CLEAR_ALL(ilu->ilu_event_hdl); 6608 return (STMF_SUCCESS); 6609 } 6610 6611 if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) { 6612 return (STMF_INVALID_ARG); 6613 } 6614 6615 STMF_EVENT_REMOVE(ilu->ilu_event_hdl, eventid); 6616 return (STMF_SUCCESS); 6617 } 6618 6619 stmf_status_t 6620 stmf_lport_add_event(stmf_local_port_t *lport, int eventid) 6621 { 6622 stmf_i_local_port_t *ilport = 6623 (stmf_i_local_port_t *)lport->lport_stmf_private; 6624 6625 if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) { 6626 return (STMF_INVALID_ARG); 6627 } 6628 6629 STMF_EVENT_ADD(ilport->ilport_event_hdl, eventid); 6630 return (STMF_SUCCESS); 6631 } 6632 6633 stmf_status_t 6634 stmf_lport_remove_event(stmf_local_port_t *lport, int eventid) 6635 { 6636 stmf_i_local_port_t *ilport = 6637 (stmf_i_local_port_t *)lport->lport_stmf_private; 6638 6639 if (eventid == STMF_EVENT_ALL) { 6640 STMF_EVENT_CLEAR_ALL(ilport->ilport_event_hdl); 6641 return (STMF_SUCCESS); 6642 } 6643 6644 if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) { 6645 return (STMF_INVALID_ARG); 6646 } 6647 6648 STMF_EVENT_REMOVE(ilport->ilport_event_hdl, eventid); 6649 return (STMF_SUCCESS); 6650 } 6651 6652 void 6653 stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid, void *arg, uint32_t flags) 6654 { 6655 if (STMF_EVENT_ENABLED(ilu->ilu_event_hdl, eventid) && 6656 (ilu->ilu_lu->lu_event_handler != NULL)) { 6657 ilu->ilu_lu->lu_event_handler(ilu->ilu_lu, eventid, arg, flags); 6658 } 6659 } 6660 6661 void 6662 stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid, void *arg, 6663 uint32_t flags) 6664 { 6665 if (STMF_EVENT_ENABLED(ilport->ilport_event_hdl, eventid) && 6666 (ilport->ilport_lport->lport_event_handler != NULL)) { 6667 ilport->ilport_lport->lport_event_handler( 6668 ilport->ilport_lport, eventid, arg, flags); 6669 } 6670 } 6671 6672 void 6673 stmf_svc_init() 6674 { 6675 if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) 6676 return; 6677 stmf_state.stmf_svc_taskq = ddi_taskq_create(0, "STMF_SVC_TASKQ", 1, 6678 TASKQ_DEFAULTPRI, 0); 6679 (void) ddi_taskq_dispatch(stmf_state.stmf_svc_taskq, 6680 stmf_svc, 0, DDI_SLEEP); 6681 } 6682 6683 stmf_status_t 6684 stmf_svc_fini() 6685 { 6686 uint32_t i; 6687 6688 mutex_enter(&stmf_state.stmf_lock); 6689 if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) { 6690 stmf_state.stmf_svc_flags |= STMF_SVC_TERMINATE; 6691 cv_signal(&stmf_state.stmf_cv); 6692 } 6693 mutex_exit(&stmf_state.stmf_lock); 6694 6695 /* Wait for 5 seconds */ 6696 for (i = 0; i < 500; i++) { 6697 if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) 6698 delay(drv_usectohz(10000)); 6699 else 6700 break; 6701 } 6702 if (i == 500) 6703 return (STMF_BUSY); 6704 6705 ddi_taskq_destroy(stmf_state.stmf_svc_taskq); 6706 6707 return (STMF_SUCCESS); 6708 } 6709 6710 /* ARGSUSED */ 6711 void 6712 stmf_svc(void *arg) 6713 { 6714 stmf_svc_req_t *req, **preq; 6715 clock_t td; 6716 clock_t drain_start, drain_next = 0; 6717 clock_t timing_start, timing_next = 0; 6718 clock_t worker_delay = 0; 6719 int deq; 6720 stmf_lu_t *lu; 6721 stmf_i_lu_t *ilu; 6722 stmf_local_port_t *lport; 6723 stmf_i_local_port_t *ilport, *next_ilport; 6724 stmf_i_scsi_session_t *iss; 6725 6726 td = drv_usectohz(20000); 6727 6728 mutex_enter(&stmf_state.stmf_lock); 6729 stmf_state.stmf_svc_flags |= STMF_SVC_STARTED | STMF_SVC_ACTIVE; 6730 6731 stmf_svc_loop: 6732 if (stmf_state.stmf_svc_flags & STMF_SVC_TERMINATE) { 6733 stmf_state.stmf_svc_flags &= 6734 ~(STMF_SVC_STARTED | STMF_SVC_ACTIVE); 6735 mutex_exit(&stmf_state.stmf_lock); 6736 return; 6737 } 6738 6739 if (stmf_state.stmf_svc_active) { 6740 int waitq_add = 0; 6741 req = stmf_state.stmf_svc_active; 6742 stmf_state.stmf_svc_active = req->svc_next; 6743 6744 switch (req->svc_cmd) { 6745 case STMF_CMD_LPORT_ONLINE: 6746 /* Fallthrough */ 6747 case STMF_CMD_LPORT_OFFLINE: 6748 /* Fallthrough */ 6749 case STMF_CMD_LU_ONLINE: 6750 /* Nothing to do */ 6751 waitq_add = 1; 6752 break; 6753 6754 case STMF_CMD_LU_OFFLINE: 6755 /* Remove all mappings of this LU */ 6756 stmf_session_lu_unmapall((stmf_lu_t *)req->svc_obj); 6757 /* Kill all the pending I/Os for this LU */ 6758 mutex_exit(&stmf_state.stmf_lock); 6759 stmf_task_lu_killall((stmf_lu_t *)req->svc_obj, NULL, 6760 STMF_ABORTED); 6761 mutex_enter(&stmf_state.stmf_lock); 6762 waitq_add = 1; 6763 break; 6764 default: 6765 cmn_err(CE_PANIC, "stmf_svc: unknown cmd %d", 6766 req->svc_cmd); 6767 } 6768 6769 if (waitq_add) { 6770 /* Put it in the wait queue */ 6771 req->svc_next = stmf_state.stmf_svc_waiting; 6772 stmf_state.stmf_svc_waiting = req; 6773 } 6774 } 6775 6776 /* The waiting list is not going to be modified by anybody else */ 6777 mutex_exit(&stmf_state.stmf_lock); 6778 6779 for (preq = &stmf_state.stmf_svc_waiting; (*preq) != NULL; ) { 6780 req = *preq; 6781 deq = 0; 6782 switch (req->svc_cmd) { 6783 case STMF_CMD_LU_ONLINE: 6784 lu = (stmf_lu_t *)req->svc_obj; 6785 deq = 1; 6786 lu->lu_ctl(lu, req->svc_cmd, &req->svc_info); 6787 break; 6788 6789 case STMF_CMD_LU_OFFLINE: 6790 lu = (stmf_lu_t *)req->svc_obj; 6791 ilu = (stmf_i_lu_t *)lu->lu_stmf_private; 6792 if (ilu->ilu_ntasks != ilu->ilu_ntasks_free) 6793 break; 6794 deq = 1; 6795 lu->lu_ctl(lu, req->svc_cmd, &req->svc_info); 6796 break; 6797 6798 case STMF_CMD_LPORT_OFFLINE: 6799 /* Fallthrough */ 6800 case STMF_CMD_LPORT_ONLINE: 6801 lport = (stmf_local_port_t *)req->svc_obj; 6802 deq = 1; 6803 lport->lport_ctl(lport, req->svc_cmd, &req->svc_info); 6804 break; 6805 } 6806 if (deq) { 6807 *preq = req->svc_next; 6808 kmem_free(req, req->svc_req_alloc_size); 6809 } else { 6810 preq = &req->svc_next; 6811 } 6812 } 6813 6814 mutex_enter(&stmf_state.stmf_lock); 6815 if (stmf_state.stmf_svc_active == NULL) { 6816 /* Do timeouts */ 6817 if (stmf_state.stmf_nlus && 6818 ((!timing_next) || (ddi_get_lbolt() >= timing_next))) { 6819 if (!stmf_state.stmf_svc_ilu_timing) { 6820 /* we are starting a new round */ 6821 stmf_state.stmf_svc_ilu_timing = 6822 stmf_state.stmf_ilulist; 6823 timing_start = ddi_get_lbolt(); 6824 } 6825 stmf_check_ilu_timing(); 6826 if (!stmf_state.stmf_svc_ilu_timing) { 6827 /* we finished a complete round */ 6828 timing_next = 6829 timing_start + drv_usectohz(5*1000*1000); 6830 } else { 6831 /* we still have some ilu items to check */ 6832 timing_next = 6833 ddi_get_lbolt() + drv_usectohz(1*1000*1000); 6834 } 6835 if (stmf_state.stmf_svc_active) 6836 goto stmf_svc_loop; 6837 } 6838 /* Check if there are free tasks to clear */ 6839 if (stmf_state.stmf_nlus && 6840 ((!drain_next) || (ddi_get_lbolt() >= drain_next))) { 6841 if (!stmf_state.stmf_svc_ilu_draining) { 6842 /* we are starting a new round */ 6843 stmf_state.stmf_svc_ilu_draining = 6844 stmf_state.stmf_ilulist; 6845 drain_start = ddi_get_lbolt(); 6846 } 6847 stmf_check_freetask(); 6848 if (!stmf_state.stmf_svc_ilu_draining) { 6849 /* we finished a complete round */ 6850 drain_next = 6851 drain_start + drv_usectohz(10*1000*1000); 6852 } else { 6853 /* we still have some ilu items to check */ 6854 drain_next = 6855 ddi_get_lbolt() + drv_usectohz(1*1000*1000); 6856 } 6857 if (stmf_state.stmf_svc_active) 6858 goto stmf_svc_loop; 6859 } 6860 6861 /* Check if we need to run worker_mgmt */ 6862 if (ddi_get_lbolt() > worker_delay) { 6863 stmf_worker_mgmt(); 6864 worker_delay = ddi_get_lbolt() + 6865 stmf_worker_mgmt_delay; 6866 } 6867 6868 /* Check if any active session got its 1st LUN */ 6869 if (stmf_state.stmf_process_initial_luns) { 6870 int stmf_level = 0; 6871 int port_level; 6872 for (ilport = stmf_state.stmf_ilportlist; ilport; 6873 ilport = next_ilport) { 6874 next_ilport = ilport->ilport_next; 6875 if ((ilport->ilport_flags & 6876 ILPORT_SS_GOT_INITIAL_LUNS) == 0) { 6877 continue; 6878 } 6879 port_level = 0; 6880 rw_enter(&ilport->ilport_lock, RW_READER); 6881 for (iss = ilport->ilport_ss_list; iss; 6882 iss = iss->iss_next) { 6883 if ((iss->iss_flags & 6884 ISS_GOT_INITIAL_LUNS) == 0) { 6885 continue; 6886 } 6887 port_level++; 6888 stmf_level++; 6889 atomic_and_32(&iss->iss_flags, 6890 ~ISS_GOT_INITIAL_LUNS); 6891 atomic_or_32(&iss->iss_flags, 6892 ISS_EVENT_ACTIVE); 6893 rw_exit(&ilport->ilport_lock); 6894 mutex_exit(&stmf_state.stmf_lock); 6895 stmf_generate_lport_event(ilport, 6896 LPORT_EVENT_INITIAL_LUN_MAPPED, 6897 iss->iss_ss, 0); 6898 atomic_and_32(&iss->iss_flags, 6899 ~ISS_EVENT_ACTIVE); 6900 mutex_enter(&stmf_state.stmf_lock); 6901 /* 6902 * scan all the ilports again as the 6903 * ilport list might have changed. 6904 */ 6905 next_ilport = 6906 stmf_state.stmf_ilportlist; 6907 break; 6908 } 6909 if (port_level == 0) { 6910 atomic_and_32(&ilport->ilport_flags, 6911 ~ILPORT_SS_GOT_INITIAL_LUNS); 6912 } 6913 /* drop the lock if we are holding it. */ 6914 if (rw_lock_held(&ilport->ilport_lock)) 6915 rw_exit(&ilport->ilport_lock); 6916 6917 /* Max 4 session at a time */ 6918 if (stmf_level >= 4) { 6919 break; 6920 } 6921 } 6922 if (stmf_level == 0) { 6923 stmf_state.stmf_process_initial_luns = 0; 6924 } 6925 } 6926 6927 stmf_state.stmf_svc_flags &= ~STMF_SVC_ACTIVE; 6928 (void) cv_reltimedwait(&stmf_state.stmf_cv, 6929 &stmf_state.stmf_lock, td, TR_CLOCK_TICK); 6930 stmf_state.stmf_svc_flags |= STMF_SVC_ACTIVE; 6931 } 6932 goto stmf_svc_loop; 6933 } 6934 6935 void 6936 stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info) 6937 { 6938 stmf_svc_req_t *req; 6939 int s; 6940 6941 ASSERT(!mutex_owned(&stmf_state.stmf_lock)); 6942 s = sizeof (stmf_svc_req_t); 6943 if (info->st_additional_info) { 6944 s += strlen(info->st_additional_info) + 1; 6945 } 6946 req = kmem_zalloc(s, KM_SLEEP); 6947 6948 req->svc_cmd = cmd; 6949 req->svc_obj = obj; 6950 req->svc_info.st_rflags = info->st_rflags; 6951 if (info->st_additional_info) { 6952 req->svc_info.st_additional_info = (char *)(GET_BYTE_OFFSET(req, 6953 sizeof (stmf_svc_req_t))); 6954 (void) strcpy(req->svc_info.st_additional_info, 6955 info->st_additional_info); 6956 } 6957 req->svc_req_alloc_size = s; 6958 6959 mutex_enter(&stmf_state.stmf_lock); 6960 req->svc_next = stmf_state.stmf_svc_active; 6961 stmf_state.stmf_svc_active = req; 6962 if ((stmf_state.stmf_svc_flags & STMF_SVC_ACTIVE) == 0) { 6963 cv_signal(&stmf_state.stmf_cv); 6964 } 6965 mutex_exit(&stmf_state.stmf_lock); 6966 } 6967 6968 void 6969 stmf_trace(caddr_t ident, const char *fmt, ...) 6970 { 6971 va_list args; 6972 char tbuf[160]; 6973 int len; 6974 6975 if (!stmf_trace_on) 6976 return; 6977 len = snprintf(tbuf, 158, "%s:%07lu: ", ident ? ident : "", 6978 ddi_get_lbolt()); 6979 va_start(args, fmt); 6980 len += vsnprintf(tbuf + len, 158 - len, fmt, args); 6981 va_end(args); 6982 6983 if (len > 158) { 6984 len = 158; 6985 } 6986 tbuf[len++] = '\n'; 6987 tbuf[len] = 0; 6988 6989 mutex_enter(&trace_buf_lock); 6990 bcopy(tbuf, &stmf_trace_buf[trace_buf_curndx], len+1); 6991 trace_buf_curndx += len; 6992 if (trace_buf_curndx > (trace_buf_size - 320)) 6993 trace_buf_curndx = 0; 6994 mutex_exit(&trace_buf_lock); 6995 } 6996 6997 void 6998 stmf_trace_clear() 6999 { 7000 if (!stmf_trace_on) 7001 return; 7002 mutex_enter(&trace_buf_lock); 7003 trace_buf_curndx = 0; 7004 if (trace_buf_size > 0) 7005 stmf_trace_buf[0] = 0; 7006 mutex_exit(&trace_buf_lock); 7007 } 7008 7009 static void 7010 stmf_abort_task_offline(scsi_task_t *task, int offline_lu, char *info) 7011 { 7012 stmf_state_change_info_t change_info; 7013 void *ctl_private; 7014 uint32_t ctl_cmd; 7015 int msg = 0; 7016 7017 stmf_trace("FROM STMF", "abort_task_offline called for %s: %s", 7018 offline_lu ? "LU" : "LPORT", info ? info : "no additional info"); 7019 change_info.st_additional_info = info; 7020 if (offline_lu) { 7021 change_info.st_rflags = STMF_RFLAG_RESET | 7022 STMF_RFLAG_LU_ABORT; 7023 ctl_private = task->task_lu; 7024 if (((stmf_i_lu_t *) 7025 task->task_lu->lu_stmf_private)->ilu_state == 7026 STMF_STATE_ONLINE) { 7027 msg = 1; 7028 } 7029 ctl_cmd = STMF_CMD_LU_OFFLINE; 7030 } else { 7031 change_info.st_rflags = STMF_RFLAG_RESET | 7032 STMF_RFLAG_LPORT_ABORT; 7033 ctl_private = task->task_lport; 7034 if (((stmf_i_local_port_t *) 7035 task->task_lport->lport_stmf_private)->ilport_state == 7036 STMF_STATE_ONLINE) { 7037 msg = 1; 7038 } 7039 ctl_cmd = STMF_CMD_LPORT_OFFLINE; 7040 } 7041 7042 if (msg) { 7043 stmf_trace(0, "Calling stmf_ctl to offline %s : %s", 7044 offline_lu ? "LU" : "LPORT", info ? info : 7045 "<no additional info>"); 7046 } 7047 (void) stmf_ctl(ctl_cmd, ctl_private, &change_info); 7048 } 7049