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