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