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