1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * sf - Solaris Fibre Channel driver 28 * 29 * This module implements some of the Fibre Channel FC-4 layer, converting 30 * from FC frames to SCSI and back. (Note: no sequence management is done 31 * here, though.) 32 */ 33 34 #if defined(lint) && !defined(DEBUG) 35 #define DEBUG 1 36 #endif 37 38 /* 39 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 40 * Need to use the ugly RAID LUN mappings in FCP Annex D 41 * to prevent SCSA from barfing. This *REALLY* needs to 42 * be addressed by the standards committee. 43 */ 44 #define RAID_LUNS 1 45 46 #ifdef DEBUG 47 static int sfdebug = 0; 48 #include <sys/debug.h> 49 50 #define SF_DEBUG(level, args) \ 51 if (sfdebug >= (level)) sf_log args 52 #else 53 #define SF_DEBUG(level, args) 54 #endif 55 56 static int sf_bus_config_debug = 0; 57 58 /* Why do I have to do this? */ 59 #define offsetof(s, m) (size_t)(&(((s *)0)->m)) 60 61 #include <sys/scsi/scsi.h> 62 #include <sys/fc4/fcal.h> 63 #include <sys/fc4/fcp.h> 64 #include <sys/fc4/fcal_linkapp.h> 65 #include <sys/socal_cq_defs.h> 66 #include <sys/fc4/fcal_transport.h> 67 #include <sys/fc4/fcio.h> 68 #include <sys/scsi/adapters/sfvar.h> 69 #include <sys/scsi/impl/scsi_reset_notify.h> 70 #include <sys/stat.h> 71 #include <sys/varargs.h> 72 #include <sys/var.h> 73 #include <sys/thread.h> 74 #include <sys/proc.h> 75 #include <sys/kstat.h> 76 #include <sys/devctl.h> 77 #include <sys/scsi/targets/ses.h> 78 #include <sys/callb.h> 79 80 static int sf_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 81 static int sf_attach(dev_info_t *, ddi_attach_cmd_t); 82 static int sf_detach(dev_info_t *, ddi_detach_cmd_t); 83 static void sf_softstate_unlink(struct sf *); 84 static int sf_scsi_bus_config(dev_info_t *parent, uint_t flag, 85 ddi_bus_config_op_t op, void *arg, dev_info_t **childp); 86 static int sf_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 87 ddi_bus_config_op_t op, void *arg); 88 static int sf_scsi_tgt_init(dev_info_t *, dev_info_t *, 89 scsi_hba_tran_t *, struct scsi_device *); 90 static void sf_scsi_tgt_free(dev_info_t *, dev_info_t *, 91 scsi_hba_tran_t *, struct scsi_device *); 92 static int sf_pkt_alloc_extern(struct sf *, struct sf_pkt *, 93 int, int, int); 94 static void sf_pkt_destroy_extern(struct sf *, struct sf_pkt *); 95 static struct scsi_pkt *sf_scsi_init_pkt(struct scsi_address *, 96 struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(), caddr_t); 97 static void sf_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *); 98 static void sf_scsi_dmafree(struct scsi_address *, struct scsi_pkt *); 99 static void sf_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *); 100 static int sf_scsi_reset_notify(struct scsi_address *, int, 101 void (*)(caddr_t), caddr_t); 102 static int sf_scsi_get_name(struct scsi_device *, char *, int); 103 static int sf_scsi_get_bus_addr(struct scsi_device *, char *, int); 104 static int sf_add_cr_pool(struct sf *); 105 static int sf_cr_alloc(struct sf *, struct sf_pkt *, int (*)()); 106 static void sf_cr_free(struct sf_cr_pool *, struct sf_pkt *); 107 static void sf_crpool_free(struct sf *); 108 static int sf_kmem_cache_constructor(void *, void *, int); 109 static void sf_kmem_cache_destructor(void *, void *); 110 static void sf_statec_callback(void *, int); 111 static int sf_login(struct sf *, uchar_t, uchar_t, uint_t, int); 112 static int sf_els_transport(struct sf *, struct sf_els_hdr *); 113 static void sf_els_callback(struct fcal_packet *); 114 static int sf_do_prli(struct sf *, struct sf_els_hdr *, struct la_els_logi *); 115 static int sf_do_adisc(struct sf *, struct sf_els_hdr *); 116 static int sf_do_reportlun(struct sf *, struct sf_els_hdr *, 117 struct sf_target *); 118 static void sf_reportlun_callback(struct fcal_packet *); 119 static int sf_do_inquiry(struct sf *, struct sf_els_hdr *, 120 struct sf_target *); 121 static void sf_inq_callback(struct fcal_packet *); 122 static struct fcal_packet *sf_els_alloc(struct sf *, uchar_t, int, int, 123 int, caddr_t *, caddr_t *); 124 static void sf_els_free(struct fcal_packet *); 125 static struct sf_target *sf_create_target(struct sf *, 126 struct sf_els_hdr *, int, int64_t); 127 #ifdef RAID_LUNS 128 static struct sf_target *sf_lookup_target(struct sf *, uchar_t *, int); 129 #else 130 static struct sf_target *sf_lookup_target(struct sf *, uchar_t *, int64_t); 131 #endif 132 static void sf_finish_init(struct sf *, int); 133 static void sf_offline_target(struct sf *, struct sf_target *); 134 static void sf_create_devinfo(struct sf *, struct sf_target *, int); 135 static int sf_create_props(dev_info_t *, struct sf_target *, int); 136 static int sf_commoncap(struct scsi_address *, char *, int, int, int); 137 static int sf_getcap(struct scsi_address *, char *, int); 138 static int sf_setcap(struct scsi_address *, char *, int, int); 139 static int sf_abort(struct scsi_address *, struct scsi_pkt *); 140 static int sf_reset(struct scsi_address *, int); 141 static void sf_abort_all(struct sf *, struct sf_target *, int, int, int); 142 static int sf_start(struct scsi_address *, struct scsi_pkt *); 143 static int sf_start_internal(struct sf *, struct sf_pkt *); 144 static void sf_fill_ids(struct sf *, struct sf_pkt *, struct sf_target *); 145 static int sf_prepare_pkt(struct sf *, struct sf_pkt *, struct sf_target *); 146 static int sf_dopoll(struct sf *, struct sf_pkt *); 147 static void sf_cmd_callback(struct fcal_packet *); 148 static void sf_throttle(struct sf *); 149 static void sf_watch(void *); 150 static void sf_throttle_start(struct sf *); 151 static void sf_check_targets(struct sf *); 152 static void sf_check_reset_delay(void *); 153 static int sf_target_timeout(struct sf *, struct sf_pkt *); 154 static void sf_force_lip(struct sf *); 155 static void sf_unsol_els_callback(void *, soc_response_t *, caddr_t); 156 static struct sf_els_hdr *sf_els_timeout(struct sf *, struct sf_els_hdr *); 157 /*PRINTFLIKE3*/ 158 static void sf_log(struct sf *, int, const char *, ...); 159 static int sf_kstat_update(kstat_t *, int); 160 static int sf_open(dev_t *, int, int, cred_t *); 161 static int sf_close(dev_t, int, int, cred_t *); 162 static int sf_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 163 static struct sf_target *sf_get_target_from_dip(struct sf *, dev_info_t *); 164 static int sf_bus_get_eventcookie(dev_info_t *, dev_info_t *, char *, 165 ddi_eventcookie_t *); 166 static int sf_bus_add_eventcall(dev_info_t *, dev_info_t *, 167 ddi_eventcookie_t, void (*)(), void *, ddi_callback_id_t *cb_id); 168 static int sf_bus_remove_eventcall(dev_info_t *devi, ddi_callback_id_t cb_id); 169 static int sf_bus_post_event(dev_info_t *, dev_info_t *, 170 ddi_eventcookie_t, void *); 171 172 static void sf_hp_daemon(void *); 173 174 /* 175 * this is required to be able to supply a control node 176 * where ioctls can be executed 177 */ 178 struct cb_ops sf_cb_ops = { 179 sf_open, /* open */ 180 sf_close, /* close */ 181 nodev, /* strategy */ 182 nodev, /* print */ 183 nodev, /* dump */ 184 nodev, /* read */ 185 nodev, /* write */ 186 sf_ioctl, /* ioctl */ 187 nodev, /* devmap */ 188 nodev, /* mmap */ 189 nodev, /* segmap */ 190 nochpoll, /* poll */ 191 ddi_prop_op, /* cb_prop_op */ 192 0, /* streamtab */ 193 D_MP | D_NEW | D_HOTPLUG /* driver flags */ 194 195 }; 196 197 /* 198 * autoconfiguration routines. 199 */ 200 static struct dev_ops sf_ops = { 201 DEVO_REV, /* devo_rev, */ 202 0, /* refcnt */ 203 sf_info, /* info */ 204 nulldev, /* identify */ 205 nulldev, /* probe */ 206 sf_attach, /* attach */ 207 sf_detach, /* detach */ 208 nodev, /* reset */ 209 &sf_cb_ops, /* driver operations */ 210 NULL, /* bus operations */ 211 NULL, /* power management */ 212 ddi_quiesce_not_supported, /* devo_quiesce */ 213 }; 214 215 /* to ensure this module gets loaded in memory when we do */ 216 char _depends_on[] = "misc/scsi"; 217 218 #define SF_NAME "FC-AL FCP Nexus Driver" /* Name of the module. */ 219 static char sf_version[] = "1.72 08/19/2008"; /* version of the module */ 220 221 static struct modldrv modldrv = { 222 &mod_driverops, /* Type of module. This one is a driver */ 223 SF_NAME, 224 &sf_ops, /* driver ops */ 225 }; 226 227 static struct modlinkage modlinkage = { 228 MODREV_1, (void *)&modldrv, NULL 229 }; 230 231 /* XXXXXX The following is here to handle broken targets -- remove it later */ 232 static int sf_reportlun_forever = 0; 233 /* XXXXXX */ 234 static int sf_lip_on_plogo = 0; 235 static int sf_els_retries = SF_ELS_RETRIES; 236 static struct sf *sf_head = NULL; 237 static int sf_target_scan_cnt = 4; 238 static int sf_pkt_scan_cnt = 5; 239 static int sf_pool_scan_cnt = 1800; 240 static void *sf_state = NULL; 241 static int sf_watchdog_init = 0; 242 static int sf_watchdog_time = 0; 243 static int sf_watchdog_timeout = 1; 244 static int sf_watchdog_tick; 245 static int sf_watch_running = 0; 246 static timeout_id_t sf_watchdog_id; 247 static timeout_id_t sf_reset_timeout_id; 248 static int sf_max_targets = SF_MAX_TARGETS; 249 static kmutex_t sf_global_mutex; 250 static int sf_core = 0; 251 int *sf_token = NULL; /* Must not be static or lint complains. */ 252 static kcondvar_t sf_watch_cv; 253 extern pri_t minclsyspri; 254 static ddi_eventcookie_t sf_insert_eid; 255 static ddi_eventcookie_t sf_remove_eid; 256 257 static ndi_event_definition_t sf_event_defs[] = { 258 { SF_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL, 0 }, 259 { SF_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT, 0 } 260 }; 261 262 #define SF_N_NDI_EVENTS \ 263 (sizeof (sf_event_defs) / sizeof (ndi_event_definition_t)) 264 265 #ifdef DEBUG 266 static int sf_lip_flag = 1; /* bool: to allow LIPs */ 267 static int sf_reset_flag = 1; /* bool: to allow reset after LIP */ 268 static int sf_abort_flag = 0; /* bool: to do just one abort */ 269 #endif 270 271 extern int64_t ddi_get_lbolt64(void); 272 273 /* 274 * for converting between target number (switch) and hard address/AL_PA 275 */ 276 static uchar_t sf_switch_to_alpa[] = { 277 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6, 278 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 279 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 280 0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 281 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97, 282 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79, 283 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 284 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56, 285 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 286 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35, 287 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 288 0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 289 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01 290 }; 291 292 static uchar_t sf_alpa_to_switch[] = { 293 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 294 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 295 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 296 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 297 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 298 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 299 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 300 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 301 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 302 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 303 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 304 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 305 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 306 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 307 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 308 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 309 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 310 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 311 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 312 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 313 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 314 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 315 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 316 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 317 }; 318 319 /* 320 * these macros call the proper transport-layer function given 321 * a particular transport 322 */ 323 #define soc_transport(a, b, c, d) (*a->fcal_ops->fcal_transport)(b, c, d) 324 #define soc_transport_poll(a, b, c, d)\ 325 (*a->fcal_ops->fcal_transport_poll)(b, c, d) 326 #define soc_get_lilp_map(a, b, c, d, e)\ 327 (*a->fcal_ops->fcal_lilp_map)(b, c, d, e) 328 #define soc_force_lip(a, b, c, d, e)\ 329 (*a->fcal_ops->fcal_force_lip)(b, c, d, e) 330 #define soc_abort(a, b, c, d, e)\ 331 (*a->fcal_ops->fcal_abort_cmd)(b, c, d, e) 332 #define soc_force_reset(a, b, c, d)\ 333 (*a->fcal_ops->fcal_force_reset)(b, c, d) 334 #define soc_add_ulp(a, b, c, d, e, f, g, h)\ 335 (*a->fcal_ops->fcal_add_ulp)(b, c, d, e, f, g, h) 336 #define soc_remove_ulp(a, b, c, d, e)\ 337 (*a->fcal_ops->fcal_remove_ulp)(b, c, d, e) 338 #define soc_take_core(a, b) (*a->fcal_ops->fcal_take_core)(b) 339 340 341 /* power management property defines (should be in a common include file?) */ 342 #define PM_HARDWARE_STATE_PROP "pm-hardware-state" 343 #define PM_NEEDS_SUSPEND_RESUME "needs-suspend-resume" 344 345 346 /* node properties */ 347 #define NODE_WWN_PROP "node-wwn" 348 #define PORT_WWN_PROP "port-wwn" 349 #define LIP_CNT_PROP "lip-count" 350 #define TARGET_PROP "target" 351 #define LUN_PROP "lun" 352 353 354 /* 355 * initialize this driver and install this module 356 */ 357 int 358 _init(void) 359 { 360 int i; 361 362 i = ddi_soft_state_init(&sf_state, sizeof (struct sf), 363 SF_INIT_ITEMS); 364 if (i != 0) 365 return (i); 366 367 if ((i = scsi_hba_init(&modlinkage)) != 0) { 368 ddi_soft_state_fini(&sf_state); 369 return (i); 370 } 371 372 mutex_init(&sf_global_mutex, NULL, MUTEX_DRIVER, NULL); 373 sf_watch_running = 0; 374 cv_init(&sf_watch_cv, NULL, CV_DRIVER, NULL); 375 376 if ((i = mod_install(&modlinkage)) != 0) { 377 mutex_destroy(&sf_global_mutex); 378 cv_destroy(&sf_watch_cv); 379 scsi_hba_fini(&modlinkage); 380 ddi_soft_state_fini(&sf_state); 381 return (i); 382 } 383 384 return (i); 385 } 386 387 388 /* 389 * remove this driver module from the system 390 */ 391 int 392 _fini(void) 393 { 394 int i; 395 396 if ((i = mod_remove(&modlinkage)) == 0) { 397 scsi_hba_fini(&modlinkage); 398 mutex_destroy(&sf_global_mutex); 399 cv_destroy(&sf_watch_cv); 400 ddi_soft_state_fini(&sf_state); 401 } 402 return (i); 403 } 404 405 406 int 407 _info(struct modinfo *modinfop) 408 { 409 return (mod_info(&modlinkage, modinfop)); 410 } 411 412 /* 413 * Given the device number return the devinfo pointer or instance 414 */ 415 /*ARGSUSED*/ 416 static int 417 sf_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 418 { 419 int instance = SF_MINOR2INST(getminor((dev_t)arg)); 420 struct sf *sf; 421 422 switch (infocmd) { 423 case DDI_INFO_DEVT2DEVINFO: 424 sf = ddi_get_soft_state(sf_state, instance); 425 if (sf != NULL) 426 *result = sf->sf_dip; 427 else { 428 *result = NULL; 429 return (DDI_FAILURE); 430 } 431 break; 432 433 case DDI_INFO_DEVT2INSTANCE: 434 *result = (void *)(uintptr_t)instance; 435 break; 436 default: 437 return (DDI_FAILURE); 438 } 439 return (DDI_SUCCESS); 440 } 441 442 /* 443 * either attach or resume this driver 444 */ 445 static int 446 sf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 447 { 448 int instance; 449 int mutex_initted = FALSE; 450 uint_t ccount; 451 size_t i, real_size; 452 struct fcal_transport *handle; 453 char buf[64]; 454 struct sf *sf, *tsf; 455 scsi_hba_tran_t *tran = NULL; 456 int handle_bound = FALSE; 457 kthread_t *tp; 458 459 460 switch ((int)cmd) { 461 462 case DDI_RESUME: 463 464 /* 465 * we've previously been SF_STATE_OFFLINEd by a DDI_SUSPEND, 466 * so time to undo that and get going again by forcing a 467 * lip 468 */ 469 470 instance = ddi_get_instance(dip); 471 472 sf = ddi_get_soft_state(sf_state, instance); 473 SF_DEBUG(2, (sf, CE_CONT, 474 "sf_attach: DDI_RESUME for sf%d\n", instance)); 475 if (sf == NULL) { 476 cmn_err(CE_WARN, "sf%d: bad soft state", instance); 477 return (DDI_FAILURE); 478 } 479 480 /* 481 * clear suspended flag so that normal operations can resume 482 */ 483 mutex_enter(&sf->sf_mutex); 484 sf->sf_state &= ~SF_STATE_SUSPENDED; 485 mutex_exit(&sf->sf_mutex); 486 487 /* 488 * force a login by setting our state to offline 489 */ 490 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT; 491 sf->sf_state = SF_STATE_OFFLINE; 492 493 /* 494 * call transport routine to register state change and 495 * ELS callback routines (to register us as a ULP) 496 */ 497 soc_add_ulp(sf->sf_sochandle, sf->sf_socp, 498 sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, 499 sf_statec_callback, sf_unsol_els_callback, NULL, sf); 500 501 /* 502 * call transport routine to force loop initialization 503 */ 504 (void) soc_force_lip(sf->sf_sochandle, sf->sf_socp, 505 sf->sf_sochandle->fcal_portno, 0, FCAL_NO_LIP); 506 507 /* 508 * increment watchdog init flag, setting watchdog timeout 509 * if we are the first (since somebody has to do it) 510 */ 511 mutex_enter(&sf_global_mutex); 512 if (!sf_watchdog_init++) { 513 mutex_exit(&sf_global_mutex); 514 sf_watchdog_id = timeout(sf_watch, 515 (caddr_t)0, sf_watchdog_tick); 516 } else { 517 mutex_exit(&sf_global_mutex); 518 } 519 520 return (DDI_SUCCESS); 521 522 case DDI_ATTACH: 523 524 /* 525 * this instance attaching for the first time 526 */ 527 528 instance = ddi_get_instance(dip); 529 530 if (ddi_soft_state_zalloc(sf_state, instance) != 531 DDI_SUCCESS) { 532 cmn_err(CE_WARN, "sf%d: failed to allocate soft state", 533 instance); 534 return (DDI_FAILURE); 535 } 536 537 sf = ddi_get_soft_state(sf_state, instance); 538 SF_DEBUG(4, (sf, CE_CONT, 539 "sf_attach: DDI_ATTACH for sf%d\n", instance)); 540 if (sf == NULL) { 541 /* this shouldn't happen since we just allocated it */ 542 cmn_err(CE_WARN, "sf%d: bad soft state", instance); 543 return (DDI_FAILURE); 544 } 545 546 /* 547 * from this point on, if there's an error, we must de-allocate 548 * soft state before returning DDI_FAILURE 549 */ 550 551 if ((handle = ddi_get_parent_data(dip)) == NULL) { 552 cmn_err(CE_WARN, 553 "sf%d: failed to obtain transport handle", 554 instance); 555 goto fail; 556 } 557 558 /* fill in our soft state structure */ 559 sf->sf_dip = dip; 560 sf->sf_state = SF_STATE_INIT; 561 sf->sf_throttle = handle->fcal_cmdmax; 562 sf->sf_sochandle = handle; 563 sf->sf_socp = handle->fcal_handle; 564 sf->sf_check_n_close = 0; 565 566 /* create a command/response buffer pool for this instance */ 567 if (sf_add_cr_pool(sf) != DDI_SUCCESS) { 568 cmn_err(CE_WARN, 569 "sf%d: failed to allocate command/response pool", 570 instance); 571 goto fail; 572 } 573 574 /* create a a cache for this instance */ 575 (void) sprintf(buf, "sf%d_cache", instance); 576 sf->sf_pkt_cache = kmem_cache_create(buf, 577 sizeof (fcal_packet_t) + sizeof (struct sf_pkt) + 578 scsi_pkt_size(), 8, 579 sf_kmem_cache_constructor, sf_kmem_cache_destructor, 580 NULL, NULL, NULL, 0); 581 if (sf->sf_pkt_cache == NULL) { 582 cmn_err(CE_WARN, "sf%d: failed to allocate kmem cache", 583 instance); 584 goto fail; 585 } 586 587 /* set up a handle and allocate memory for DMA */ 588 if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle-> 589 fcal_dmaattr, DDI_DMA_DONTWAIT, NULL, &sf-> 590 sf_lilp_dmahandle) != DDI_SUCCESS) { 591 cmn_err(CE_WARN, 592 "sf%d: failed to allocate dma handle for lilp map", 593 instance); 594 goto fail; 595 } 596 i = sizeof (struct fcal_lilp_map) + 1; 597 if (ddi_dma_mem_alloc(sf->sf_lilp_dmahandle, 598 i, sf->sf_sochandle-> 599 fcal_accattr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 600 (caddr_t *)&sf->sf_lilp_map, &real_size, 601 &sf->sf_lilp_acchandle) != DDI_SUCCESS) { 602 cmn_err(CE_WARN, "sf%d: failed to allocate lilp map", 603 instance); 604 goto fail; 605 } 606 if (real_size < i) { 607 /* no error message ??? */ 608 goto fail; /* trouble allocating memory */ 609 } 610 611 /* 612 * set up the address for the DMA transfers (getting a cookie) 613 */ 614 if (ddi_dma_addr_bind_handle(sf->sf_lilp_dmahandle, NULL, 615 (caddr_t)sf->sf_lilp_map, real_size, 616 DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 617 &sf->sf_lilp_dmacookie, &ccount) != DDI_DMA_MAPPED) { 618 cmn_err(CE_WARN, 619 "sf%d: failed to bind dma handle for lilp map", 620 instance); 621 goto fail; 622 } 623 handle_bound = TRUE; 624 /* ensure only one cookie was allocated */ 625 if (ccount != 1) { 626 goto fail; 627 } 628 629 /* ensure LILP map and DMA cookie addresses are even?? */ 630 sf->sf_lilp_map = (struct fcal_lilp_map *)(((uintptr_t)sf-> 631 sf_lilp_map + 1) & ~1); 632 sf->sf_lilp_dmacookie.dmac_address = (sf-> 633 sf_lilp_dmacookie.dmac_address + 1) & ~1; 634 635 /* set up all of our mutexes and condition variables */ 636 mutex_init(&sf->sf_mutex, NULL, MUTEX_DRIVER, NULL); 637 mutex_init(&sf->sf_cmd_mutex, NULL, MUTEX_DRIVER, NULL); 638 mutex_init(&sf->sf_cr_mutex, NULL, MUTEX_DRIVER, NULL); 639 mutex_init(&sf->sf_hp_daemon_mutex, NULL, MUTEX_DRIVER, NULL); 640 cv_init(&sf->sf_cr_cv, NULL, CV_DRIVER, NULL); 641 cv_init(&sf->sf_hp_daemon_cv, NULL, CV_DRIVER, NULL); 642 643 mutex_initted = TRUE; 644 645 /* create our devctl minor node */ 646 if (ddi_create_minor_node(dip, "devctl", S_IFCHR, 647 SF_INST2DEVCTL_MINOR(instance), 648 DDI_NT_NEXUS, 0) != DDI_SUCCESS) { 649 cmn_err(CE_WARN, "sf%d: ddi_create_minor_node failed" 650 " for devctl", instance); 651 goto fail; 652 } 653 654 /* create fc minor node */ 655 if (ddi_create_minor_node(dip, "fc", S_IFCHR, 656 SF_INST2FC_MINOR(instance), DDI_NT_FC_ATTACHMENT_POINT, 657 0) != DDI_SUCCESS) { 658 cmn_err(CE_WARN, "sf%d: ddi_create_minor_node failed" 659 " for fc", instance); 660 goto fail; 661 } 662 /* allocate a SCSI transport structure */ 663 tran = scsi_hba_tran_alloc(dip, 0); 664 if (tran == NULL) { 665 /* remove all minor nodes created */ 666 ddi_remove_minor_node(dip, NULL); 667 cmn_err(CE_WARN, "sf%d: scsi_hba_tran_alloc failed", 668 instance); 669 goto fail; 670 } 671 672 /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */ 673 scsi_size_clean(dip); /* SCSI_SIZE_CLEAN_VERIFY ok */ 674 675 /* save ptr to new transport structure and fill it in */ 676 sf->sf_tran = tran; 677 678 tran->tran_hba_private = sf; 679 tran->tran_tgt_private = NULL; 680 tran->tran_tgt_init = sf_scsi_tgt_init; 681 tran->tran_tgt_probe = NULL; 682 tran->tran_tgt_free = sf_scsi_tgt_free; 683 684 tran->tran_start = sf_start; 685 tran->tran_abort = sf_abort; 686 tran->tran_reset = sf_reset; 687 tran->tran_getcap = sf_getcap; 688 tran->tran_setcap = sf_setcap; 689 tran->tran_init_pkt = sf_scsi_init_pkt; 690 tran->tran_destroy_pkt = sf_scsi_destroy_pkt; 691 tran->tran_dmafree = sf_scsi_dmafree; 692 tran->tran_sync_pkt = sf_scsi_sync_pkt; 693 tran->tran_reset_notify = sf_scsi_reset_notify; 694 695 /* 696 * register event notification routines with scsa 697 */ 698 tran->tran_get_eventcookie = sf_bus_get_eventcookie; 699 tran->tran_add_eventcall = sf_bus_add_eventcall; 700 tran->tran_remove_eventcall = sf_bus_remove_eventcall; 701 tran->tran_post_event = sf_bus_post_event; 702 703 /* 704 * register bus configure/unconfigure 705 */ 706 tran->tran_bus_config = sf_scsi_bus_config; 707 tran->tran_bus_unconfig = sf_scsi_bus_unconfig; 708 709 /* 710 * allocate an ndi event handle 711 */ 712 sf->sf_event_defs = (ndi_event_definition_t *) 713 kmem_zalloc(sizeof (sf_event_defs), KM_SLEEP); 714 715 bcopy(sf_event_defs, sf->sf_event_defs, 716 sizeof (sf_event_defs)); 717 718 (void) ndi_event_alloc_hdl(dip, NULL, 719 &sf->sf_event_hdl, NDI_SLEEP); 720 721 sf->sf_events.ndi_events_version = NDI_EVENTS_REV1; 722 sf->sf_events.ndi_n_events = SF_N_NDI_EVENTS; 723 sf->sf_events.ndi_event_defs = sf->sf_event_defs; 724 725 if (ndi_event_bind_set(sf->sf_event_hdl, 726 &sf->sf_events, NDI_SLEEP) != NDI_SUCCESS) { 727 goto fail; 728 } 729 730 tran->tran_get_name = sf_scsi_get_name; 731 tran->tran_get_bus_addr = sf_scsi_get_bus_addr; 732 733 /* setup and attach SCSI hba transport */ 734 if (scsi_hba_attach_setup(dip, sf->sf_sochandle-> 735 fcal_dmaattr, tran, SCSI_HBA_TRAN_CLONE) != DDI_SUCCESS) { 736 cmn_err(CE_WARN, "sf%d: scsi_hba_attach_setup failed", 737 instance); 738 goto fail; 739 } 740 741 /* set up kstats */ 742 if ((sf->sf_ksp = kstat_create("sf", instance, "statistics", 743 "controller", KSTAT_TYPE_RAW, sizeof (struct sf_stats), 744 KSTAT_FLAG_VIRTUAL)) == NULL) { 745 cmn_err(CE_WARN, "sf%d: failed to create kstat", 746 instance); 747 } else { 748 sf->sf_stats.version = 2; 749 (void) sprintf(sf->sf_stats.drvr_name, 750 "%s: %s", SF_NAME, sf_version); 751 sf->sf_ksp->ks_data = (void *)&sf->sf_stats; 752 sf->sf_ksp->ks_private = sf; 753 sf->sf_ksp->ks_update = sf_kstat_update; 754 kstat_install(sf->sf_ksp); 755 } 756 757 /* create the hotplug thread */ 758 mutex_enter(&sf->sf_hp_daemon_mutex); 759 tp = thread_create(NULL, 0, 760 (void (*)())sf_hp_daemon, sf, 0, &p0, TS_RUN, minclsyspri); 761 sf->sf_hp_tid = tp->t_did; 762 mutex_exit(&sf->sf_hp_daemon_mutex); 763 764 /* add this soft state instance to the head of the list */ 765 mutex_enter(&sf_global_mutex); 766 sf->sf_next = sf_head; 767 tsf = sf_head; 768 sf_head = sf; 769 770 /* 771 * find entry in list that has the same FC-AL handle (if any) 772 */ 773 while (tsf != NULL) { 774 if (tsf->sf_socp == sf->sf_socp) { 775 break; /* found matching entry */ 776 } 777 tsf = tsf->sf_next; 778 } 779 780 if (tsf != NULL) { 781 /* if we found a matching entry keep track of it */ 782 sf->sf_sibling = tsf; 783 } 784 785 /* 786 * increment watchdog init flag, setting watchdog timeout 787 * if we are the first (since somebody has to do it) 788 */ 789 if (!sf_watchdog_init++) { 790 mutex_exit(&sf_global_mutex); 791 sf_watchdog_tick = sf_watchdog_timeout * 792 drv_usectohz(1000000); 793 sf_watchdog_id = timeout(sf_watch, 794 NULL, sf_watchdog_tick); 795 } else { 796 mutex_exit(&sf_global_mutex); 797 } 798 799 if (tsf != NULL) { 800 /* 801 * set up matching entry to be our sibling 802 */ 803 mutex_enter(&tsf->sf_mutex); 804 tsf->sf_sibling = sf; 805 mutex_exit(&tsf->sf_mutex); 806 } 807 808 /* 809 * create this property so that PM code knows we want 810 * to be suspended at PM time 811 */ 812 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, 813 PM_HARDWARE_STATE_PROP, PM_NEEDS_SUSPEND_RESUME); 814 815 /* log the fact that we have a new device */ 816 ddi_report_dev(dip); 817 818 /* 819 * force a login by setting our state to offline 820 */ 821 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT; 822 sf->sf_state = SF_STATE_OFFLINE; 823 824 /* 825 * call transport routine to register state change and 826 * ELS callback routines (to register us as a ULP) 827 */ 828 soc_add_ulp(sf->sf_sochandle, sf->sf_socp, 829 sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, 830 sf_statec_callback, sf_unsol_els_callback, NULL, sf); 831 832 /* 833 * call transport routine to force loop initialization 834 */ 835 (void) soc_force_lip(sf->sf_sochandle, sf->sf_socp, 836 sf->sf_sochandle->fcal_portno, 0, FCAL_NO_LIP); 837 sf->sf_reset_time = ddi_get_lbolt64(); 838 return (DDI_SUCCESS); 839 840 default: 841 return (DDI_FAILURE); 842 } 843 844 fail: 845 cmn_err(CE_WARN, "sf%d: failed to attach", instance); 846 847 /* 848 * Unbind and free event set 849 */ 850 if (sf->sf_event_hdl) { 851 (void) ndi_event_unbind_set(sf->sf_event_hdl, 852 &sf->sf_events, NDI_SLEEP); 853 (void) ndi_event_free_hdl(sf->sf_event_hdl); 854 } 855 856 if (sf->sf_event_defs) { 857 kmem_free(sf->sf_event_defs, sizeof (sf_event_defs)); 858 } 859 860 if (sf->sf_tran != NULL) { 861 scsi_hba_tran_free(sf->sf_tran); 862 } 863 while (sf->sf_cr_pool != NULL) { 864 sf_crpool_free(sf); 865 } 866 if (sf->sf_lilp_dmahandle != NULL) { 867 if (handle_bound) { 868 (void) ddi_dma_unbind_handle(sf->sf_lilp_dmahandle); 869 } 870 ddi_dma_free_handle(&sf->sf_lilp_dmahandle); 871 } 872 if (sf->sf_pkt_cache != NULL) { 873 kmem_cache_destroy(sf->sf_pkt_cache); 874 } 875 if (sf->sf_lilp_map != NULL) { 876 ddi_dma_mem_free(&sf->sf_lilp_acchandle); 877 } 878 if (sf->sf_ksp != NULL) { 879 kstat_delete(sf->sf_ksp); 880 } 881 if (mutex_initted) { 882 mutex_destroy(&sf->sf_mutex); 883 mutex_destroy(&sf->sf_cmd_mutex); 884 mutex_destroy(&sf->sf_cr_mutex); 885 mutex_destroy(&sf->sf_hp_daemon_mutex); 886 cv_destroy(&sf->sf_cr_cv); 887 cv_destroy(&sf->sf_hp_daemon_cv); 888 } 889 mutex_enter(&sf_global_mutex); 890 891 /* 892 * kill off the watchdog if we are the last instance 893 */ 894 if (!--sf_watchdog_init) { 895 timeout_id_t tid = sf_watchdog_id; 896 mutex_exit(&sf_global_mutex); 897 (void) untimeout(tid); 898 } else { 899 mutex_exit(&sf_global_mutex); 900 } 901 902 ddi_soft_state_free(sf_state, instance); 903 904 if (tran != NULL) { 905 /* remove all minor nodes */ 906 ddi_remove_minor_node(dip, NULL); 907 } 908 909 return (DDI_FAILURE); 910 } 911 912 913 /* ARGSUSED */ 914 static int 915 sf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 916 { 917 struct sf *sf; 918 int instance; 919 int i; 920 struct sf_target *target; 921 timeout_id_t tid; 922 923 924 925 /* NO OTHER THREADS ARE RUNNING */ 926 927 instance = ddi_get_instance(dip); 928 929 if ((sf = ddi_get_soft_state(sf_state, instance)) == NULL) { 930 cmn_err(CE_WARN, "sf_detach, sf%d: bad soft state", instance); 931 return (DDI_FAILURE); 932 } 933 934 switch (cmd) { 935 936 case DDI_SUSPEND: 937 /* 938 * suspend our instance 939 */ 940 941 SF_DEBUG(2, (sf, CE_CONT, 942 "sf_detach: DDI_SUSPEND for sf%d\n", instance)); 943 /* 944 * There is a race condition in socal where while doing 945 * callbacks if a ULP removes it self from the callback list 946 * the for loop in socal may panic as cblist is junk and 947 * while trying to get cblist->next the system will panic. 948 */ 949 950 /* call transport to remove our unregister our callbacks */ 951 soc_remove_ulp(sf->sf_sochandle, sf->sf_socp, 952 sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, sf); 953 954 /* 955 * begin process of clearing outstanding commands 956 * by issuing a lip 957 */ 958 sf_force_lip(sf); 959 960 /* 961 * toggle the device OFFLINE in order to cause 962 * outstanding commands to drain 963 */ 964 mutex_enter(&sf->sf_mutex); 965 sf->sf_lip_cnt++; 966 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT; 967 sf->sf_state = (SF_STATE_OFFLINE | SF_STATE_SUSPENDED); 968 for (i = 0; i < sf_max_targets; i++) { 969 target = sf->sf_targets[i]; 970 if (target != NULL) { 971 struct sf_target *ntarget; 972 973 mutex_enter(&target->sft_mutex); 974 if (!(target->sft_state & SF_TARGET_OFFLINE)) { 975 target->sft_state |= 976 (SF_TARGET_BUSY | SF_TARGET_MARK); 977 } 978 /* do this for all LUNs as well */ 979 for (ntarget = target->sft_next_lun; 980 ntarget; 981 ntarget = ntarget->sft_next_lun) { 982 mutex_enter(&ntarget->sft_mutex); 983 if (!(ntarget->sft_state & 984 SF_TARGET_OFFLINE)) { 985 ntarget->sft_state |= 986 (SF_TARGET_BUSY | 987 SF_TARGET_MARK); 988 } 989 mutex_exit(&ntarget->sft_mutex); 990 } 991 mutex_exit(&target->sft_mutex); 992 } 993 } 994 mutex_exit(&sf->sf_mutex); 995 mutex_enter(&sf_global_mutex); 996 997 /* 998 * kill off the watchdog if we are the last instance 999 */ 1000 if (!--sf_watchdog_init) { 1001 tid = sf_watchdog_id; 1002 mutex_exit(&sf_global_mutex); 1003 (void) untimeout(tid); 1004 } else { 1005 mutex_exit(&sf_global_mutex); 1006 } 1007 1008 return (DDI_SUCCESS); 1009 1010 case DDI_DETACH: 1011 /* 1012 * detach this instance 1013 */ 1014 1015 SF_DEBUG(2, (sf, CE_CONT, 1016 "sf_detach: DDI_DETACH for sf%d\n", instance)); 1017 1018 /* remove this "sf" from the list of sf softstates */ 1019 sf_softstate_unlink(sf); 1020 1021 /* 1022 * prior to taking any DDI_DETACH actions, toggle the 1023 * device OFFLINE in order to cause outstanding 1024 * commands to drain 1025 */ 1026 mutex_enter(&sf->sf_mutex); 1027 sf->sf_lip_cnt++; 1028 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT; 1029 sf->sf_state = SF_STATE_OFFLINE; 1030 for (i = 0; i < sf_max_targets; i++) { 1031 target = sf->sf_targets[i]; 1032 if (target != NULL) { 1033 struct sf_target *ntarget; 1034 1035 mutex_enter(&target->sft_mutex); 1036 if (!(target->sft_state & SF_TARGET_OFFLINE)) { 1037 target->sft_state |= 1038 (SF_TARGET_BUSY | SF_TARGET_MARK); 1039 } 1040 for (ntarget = target->sft_next_lun; 1041 ntarget; 1042 ntarget = ntarget->sft_next_lun) { 1043 mutex_enter(&ntarget->sft_mutex); 1044 if (!(ntarget->sft_state & 1045 SF_TARGET_OFFLINE)) { 1046 ntarget->sft_state |= 1047 (SF_TARGET_BUSY | 1048 SF_TARGET_MARK); 1049 } 1050 mutex_exit(&ntarget->sft_mutex); 1051 } 1052 mutex_exit(&target->sft_mutex); 1053 } 1054 } 1055 mutex_exit(&sf->sf_mutex); 1056 1057 /* call transport to remove and unregister our callbacks */ 1058 soc_remove_ulp(sf->sf_sochandle, sf->sf_socp, 1059 sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, sf); 1060 1061 /* 1062 * kill off the watchdog if we are the last instance 1063 */ 1064 mutex_enter(&sf_global_mutex); 1065 if (!--sf_watchdog_init) { 1066 tid = sf_watchdog_id; 1067 mutex_exit(&sf_global_mutex); 1068 (void) untimeout(tid); 1069 } else { 1070 mutex_exit(&sf_global_mutex); 1071 } 1072 1073 /* signal sf_hp_daemon() to exit and wait for exit */ 1074 mutex_enter(&sf->sf_hp_daemon_mutex); 1075 ASSERT(sf->sf_hp_tid); 1076 sf->sf_hp_exit = 1; /* flag exit */ 1077 cv_signal(&sf->sf_hp_daemon_cv); 1078 mutex_exit(&sf->sf_hp_daemon_mutex); 1079 thread_join(sf->sf_hp_tid); /* wait for hotplug to exit */ 1080 1081 /* 1082 * Unbind and free event set 1083 */ 1084 if (sf->sf_event_hdl) { 1085 (void) ndi_event_unbind_set(sf->sf_event_hdl, 1086 &sf->sf_events, NDI_SLEEP); 1087 (void) ndi_event_free_hdl(sf->sf_event_hdl); 1088 } 1089 1090 if (sf->sf_event_defs) { 1091 kmem_free(sf->sf_event_defs, sizeof (sf_event_defs)); 1092 } 1093 1094 /* detach this instance of the HBA driver */ 1095 scsi_hba_detach(dip); 1096 scsi_hba_tran_free(sf->sf_tran); 1097 1098 /* deallocate/unbind DMA handle for lilp map */ 1099 if (sf->sf_lilp_map != NULL) { 1100 (void) ddi_dma_unbind_handle(sf->sf_lilp_dmahandle); 1101 if (sf->sf_lilp_dmahandle != NULL) { 1102 ddi_dma_free_handle(&sf->sf_lilp_dmahandle); 1103 } 1104 ddi_dma_mem_free(&sf->sf_lilp_acchandle); 1105 } 1106 1107 /* 1108 * the kmem cache must be destroyed before free'ing 1109 * up the crpools 1110 * 1111 * our finagle of "ntot" and "nfree" 1112 * causes an ASSERT failure in "sf_cr_free()" 1113 * if the kmem cache is free'd after invoking 1114 * "sf_crpool_free()". 1115 */ 1116 kmem_cache_destroy(sf->sf_pkt_cache); 1117 1118 SF_DEBUG(2, (sf, CE_CONT, 1119 "sf_detach: sf_crpool_free() for instance 0x%x\n", 1120 instance)); 1121 while (sf->sf_cr_pool != NULL) { 1122 /* 1123 * set ntot to nfree for this particular entry 1124 * 1125 * this causes sf_crpool_free() to update 1126 * the cr_pool list when deallocating this entry 1127 */ 1128 sf->sf_cr_pool->ntot = sf->sf_cr_pool->nfree; 1129 sf_crpool_free(sf); 1130 } 1131 1132 /* 1133 * now that the cr_pool's are gone it's safe 1134 * to destroy all softstate mutex's and cv's 1135 */ 1136 mutex_destroy(&sf->sf_mutex); 1137 mutex_destroy(&sf->sf_cmd_mutex); 1138 mutex_destroy(&sf->sf_cr_mutex); 1139 mutex_destroy(&sf->sf_hp_daemon_mutex); 1140 cv_destroy(&sf->sf_cr_cv); 1141 cv_destroy(&sf->sf_hp_daemon_cv); 1142 1143 /* remove all minor nodes from the device tree */ 1144 ddi_remove_minor_node(dip, NULL); 1145 1146 /* remove properties created during attach() */ 1147 ddi_prop_remove_all(dip); 1148 1149 /* remove kstat's if present */ 1150 if (sf->sf_ksp != NULL) { 1151 kstat_delete(sf->sf_ksp); 1152 } 1153 1154 SF_DEBUG(2, (sf, CE_CONT, 1155 "sf_detach: ddi_soft_state_free() for instance 0x%x\n", 1156 instance)); 1157 ddi_soft_state_free(sf_state, instance); 1158 return (DDI_SUCCESS); 1159 1160 default: 1161 SF_DEBUG(2, (sf, CE_CONT, "sf_detach: sf%d unknown cmd %x\n", 1162 instance, (int)cmd)); 1163 return (DDI_FAILURE); 1164 } 1165 } 1166 1167 1168 /* 1169 * sf_softstate_unlink() - remove an sf instance from the list of softstates 1170 */ 1171 static void 1172 sf_softstate_unlink(struct sf *sf) 1173 { 1174 struct sf *sf_ptr; 1175 struct sf *sf_found_sibling; 1176 struct sf *sf_reposition = NULL; 1177 1178 1179 mutex_enter(&sf_global_mutex); 1180 while (sf_watch_running) { 1181 /* Busy working the list -- wait */ 1182 cv_wait(&sf_watch_cv, &sf_global_mutex); 1183 } 1184 if ((sf_found_sibling = sf->sf_sibling) != NULL) { 1185 /* 1186 * we have a sibling so NULL out its reference to us 1187 */ 1188 mutex_enter(&sf_found_sibling->sf_mutex); 1189 sf_found_sibling->sf_sibling = NULL; 1190 mutex_exit(&sf_found_sibling->sf_mutex); 1191 } 1192 1193 /* remove our instance from the global list */ 1194 if (sf == sf_head) { 1195 /* we were at at head of the list */ 1196 sf_head = sf->sf_next; 1197 } else { 1198 /* find us in the list */ 1199 for (sf_ptr = sf_head; 1200 sf_ptr != NULL; 1201 sf_ptr = sf_ptr->sf_next) { 1202 if (sf_ptr == sf) { 1203 break; 1204 } 1205 /* remember this place */ 1206 sf_reposition = sf_ptr; 1207 } 1208 ASSERT(sf_ptr == sf); 1209 ASSERT(sf_reposition != NULL); 1210 1211 sf_reposition->sf_next = sf_ptr->sf_next; 1212 } 1213 mutex_exit(&sf_global_mutex); 1214 } 1215 1216 1217 static int 1218 sf_scsi_bus_config(dev_info_t *parent, uint_t flag, 1219 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 1220 { 1221 int64_t reset_delay; 1222 struct sf *sf; 1223 1224 sf = ddi_get_soft_state(sf_state, ddi_get_instance(parent)); 1225 ASSERT(sf); 1226 1227 reset_delay = (int64_t)(USEC_TO_TICK(SF_INIT_WAIT_TIMEOUT)) - 1228 (ddi_get_lbolt64() - sf->sf_reset_time); 1229 if (reset_delay < 0) 1230 reset_delay = 0; 1231 1232 if (sf_bus_config_debug) 1233 flag |= NDI_DEVI_DEBUG; 1234 1235 return (ndi_busop_bus_config(parent, flag, op, 1236 arg, childp, (clock_t)reset_delay)); 1237 } 1238 1239 static int 1240 sf_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 1241 ddi_bus_config_op_t op, void *arg) 1242 { 1243 if (sf_bus_config_debug) 1244 flag |= NDI_DEVI_DEBUG; 1245 1246 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 1247 } 1248 1249 1250 /* 1251 * called by transport to initialize a SCSI target 1252 */ 1253 /* ARGSUSED */ 1254 static int 1255 sf_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 1256 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 1257 { 1258 #ifdef RAID_LUNS 1259 int lun; 1260 #else 1261 int64_t lun; 1262 #endif 1263 struct sf_target *target; 1264 struct sf *sf = (struct sf *)hba_tran->tran_hba_private; 1265 int i, t_len; 1266 unsigned int lip_cnt; 1267 unsigned char wwn[FC_WWN_SIZE]; 1268 1269 1270 /* get and validate our SCSI target ID */ 1271 i = sd->sd_address.a_target; 1272 if (i >= sf_max_targets) { 1273 return (DDI_NOT_WELL_FORMED); 1274 } 1275 1276 /* get our port WWN property */ 1277 t_len = sizeof (wwn); 1278 if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF, 1279 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, PORT_WWN_PROP, 1280 (caddr_t)&wwn, &t_len) != DDI_SUCCESS) { 1281 /* no port WWN property - ignore the OBP stub node */ 1282 return (DDI_NOT_WELL_FORMED); 1283 } 1284 1285 /* get our LIP count property */ 1286 t_len = sizeof (lip_cnt); 1287 if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF, 1288 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, LIP_CNT_PROP, 1289 (caddr_t)&lip_cnt, &t_len) != DDI_SUCCESS) { 1290 return (DDI_FAILURE); 1291 } 1292 /* and our LUN property */ 1293 t_len = sizeof (lun); 1294 if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF, 1295 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun", 1296 (caddr_t)&lun, &t_len) != DDI_SUCCESS) { 1297 return (DDI_FAILURE); 1298 } 1299 1300 /* find the target structure for this instance */ 1301 mutex_enter(&sf->sf_mutex); 1302 if ((target = sf_lookup_target(sf, wwn, lun)) == NULL) { 1303 mutex_exit(&sf->sf_mutex); 1304 return (DDI_FAILURE); 1305 } 1306 1307 mutex_enter(&target->sft_mutex); 1308 if ((sf->sf_lip_cnt == lip_cnt) && !(target->sft_state 1309 & SF_TARGET_INIT_DONE)) { 1310 /* 1311 * set links between HBA transport and target structures 1312 * and set done flag 1313 */ 1314 hba_tran->tran_tgt_private = target; 1315 target->sft_tran = hba_tran; 1316 target->sft_state |= SF_TARGET_INIT_DONE; 1317 } else { 1318 /* already initialized ?? */ 1319 mutex_exit(&target->sft_mutex); 1320 mutex_exit(&sf->sf_mutex); 1321 return (DDI_FAILURE); 1322 } 1323 mutex_exit(&target->sft_mutex); 1324 mutex_exit(&sf->sf_mutex); 1325 1326 return (DDI_SUCCESS); 1327 } 1328 1329 1330 /* 1331 * called by transport to free a target 1332 */ 1333 /* ARGSUSED */ 1334 static void 1335 sf_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 1336 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 1337 { 1338 struct sf_target *target = hba_tran->tran_tgt_private; 1339 1340 if (target != NULL) { 1341 mutex_enter(&target->sft_mutex); 1342 target->sft_tran = NULL; 1343 target->sft_state &= ~SF_TARGET_INIT_DONE; 1344 mutex_exit(&target->sft_mutex); 1345 } 1346 } 1347 1348 1349 /* 1350 * allocator for non-std size cdb/pkt_private/status -- return TRUE iff 1351 * success, else return FALSE 1352 */ 1353 /*ARGSUSED*/ 1354 static int 1355 sf_pkt_alloc_extern(struct sf *sf, struct sf_pkt *cmd, 1356 int tgtlen, int statuslen, int kf) 1357 { 1358 caddr_t scbp, tgt; 1359 int failure = FALSE; 1360 struct scsi_pkt *pkt = CMD2PKT(cmd); 1361 1362 1363 tgt = scbp = NULL; 1364 1365 if (tgtlen > PKT_PRIV_LEN) { 1366 if ((tgt = kmem_zalloc(tgtlen, kf)) == NULL) { 1367 failure = TRUE; 1368 } else { 1369 cmd->cmd_flags |= CFLAG_PRIVEXTERN; 1370 pkt->pkt_private = tgt; 1371 } 1372 } 1373 if (statuslen > EXTCMDS_STATUS_SIZE) { 1374 if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) { 1375 failure = TRUE; 1376 } else { 1377 cmd->cmd_flags |= CFLAG_SCBEXTERN; 1378 pkt->pkt_scbp = (opaque_t)scbp; 1379 } 1380 } 1381 if (failure) { 1382 sf_pkt_destroy_extern(sf, cmd); 1383 } 1384 return (failure); 1385 } 1386 1387 1388 /* 1389 * deallocator for non-std size cdb/pkt_private/status 1390 */ 1391 static void 1392 sf_pkt_destroy_extern(struct sf *sf, struct sf_pkt *cmd) 1393 { 1394 struct scsi_pkt *pkt = CMD2PKT(cmd); 1395 1396 if (cmd->cmd_flags & CFLAG_FREE) { 1397 cmn_err(CE_PANIC, 1398 "sf_scsi_impl_pktfree: freeing free packet"); 1399 _NOTE(NOT_REACHED) 1400 /* NOTREACHED */ 1401 } 1402 if (cmd->cmd_flags & CFLAG_SCBEXTERN) { 1403 kmem_free((caddr_t)pkt->pkt_scbp, 1404 (size_t)cmd->cmd_scblen); 1405 } 1406 if (cmd->cmd_flags & CFLAG_PRIVEXTERN) { 1407 kmem_free((caddr_t)pkt->pkt_private, 1408 (size_t)cmd->cmd_privlen); 1409 } 1410 1411 cmd->cmd_flags = CFLAG_FREE; 1412 kmem_cache_free(sf->sf_pkt_cache, (void *)cmd); 1413 } 1414 1415 1416 /* 1417 * create or initialize a SCSI packet -- called internally and 1418 * by the transport 1419 */ 1420 static struct scsi_pkt * 1421 sf_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 1422 struct buf *bp, int cmdlen, int statuslen, int tgtlen, 1423 int flags, int (*callback)(), caddr_t arg) 1424 { 1425 int kf; 1426 int failure = FALSE; 1427 struct sf_pkt *cmd; 1428 struct sf *sf = ADDR2SF(ap); 1429 struct sf_target *target = ADDR2TARGET(ap); 1430 struct sf_pkt *new_cmd = NULL; 1431 struct fcal_packet *fpkt; 1432 fc_frame_header_t *hp; 1433 struct fcp_cmd *fcmd; 1434 1435 1436 /* 1437 * If we've already allocated a pkt once, 1438 * this request is for dma allocation only. 1439 */ 1440 if (pkt == NULL) { 1441 1442 /* 1443 * First step of sf_scsi_init_pkt: pkt allocation 1444 */ 1445 if (cmdlen > FCP_CDB_SIZE) { 1446 return (NULL); 1447 } 1448 1449 kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP; 1450 1451 if ((cmd = kmem_cache_alloc(sf->sf_pkt_cache, kf)) != NULL) { 1452 /* 1453 * Selective zeroing of the pkt. 1454 */ 1455 1456 cmd->cmd_flags = 0; 1457 cmd->cmd_forw = 0; 1458 cmd->cmd_back = 0; 1459 cmd->cmd_next = 0; 1460 cmd->cmd_pkt = (struct scsi_pkt *)((char *)cmd + 1461 sizeof (struct sf_pkt) + sizeof (struct 1462 fcal_packet)); 1463 cmd->cmd_fp_pkt = (struct fcal_packet *)((char *)cmd + 1464 sizeof (struct sf_pkt)); 1465 cmd->cmd_fp_pkt->fcal_pkt_private = (opaque_t)cmd; 1466 cmd->cmd_state = SF_STATE_IDLE; 1467 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 1468 cmd->cmd_pkt->pkt_scbp = (opaque_t)cmd->cmd_scsi_scb; 1469 cmd->cmd_pkt->pkt_comp = NULL; 1470 cmd->cmd_pkt->pkt_flags = 0; 1471 cmd->cmd_pkt->pkt_time = 0; 1472 cmd->cmd_pkt->pkt_resid = 0; 1473 cmd->cmd_pkt->pkt_reason = 0; 1474 cmd->cmd_cdblen = (uchar_t)cmdlen; 1475 cmd->cmd_scblen = statuslen; 1476 cmd->cmd_privlen = tgtlen; 1477 cmd->cmd_pkt->pkt_address = *ap; 1478 1479 /* zero pkt_private */ 1480 (int *)(cmd->cmd_pkt->pkt_private = 1481 cmd->cmd_pkt_private); 1482 bzero((caddr_t)cmd->cmd_pkt->pkt_private, 1483 PKT_PRIV_LEN); 1484 } else { 1485 failure = TRUE; 1486 } 1487 1488 if (failure || 1489 (tgtlen > PKT_PRIV_LEN) || 1490 (statuslen > EXTCMDS_STATUS_SIZE)) { 1491 if (!failure) { 1492 /* need to allocate more space */ 1493 failure = sf_pkt_alloc_extern(sf, cmd, 1494 tgtlen, statuslen, kf); 1495 } 1496 if (failure) { 1497 return (NULL); 1498 } 1499 } 1500 1501 fpkt = cmd->cmd_fp_pkt; 1502 if (cmd->cmd_block == NULL) { 1503 1504 /* allocate cmd/response pool buffers */ 1505 if (sf_cr_alloc(sf, cmd, callback) == DDI_FAILURE) { 1506 sf_pkt_destroy_extern(sf, cmd); 1507 return (NULL); 1508 } 1509 1510 /* fill in the FC-AL packet */ 1511 fpkt->fcal_pkt_cookie = sf->sf_socp; 1512 fpkt->fcal_pkt_comp = sf_cmd_callback; 1513 fpkt->fcal_pkt_flags = 0; 1514 fpkt->fcal_magic = FCALP_MAGIC; 1515 fpkt->fcal_socal_request.sr_soc_hdr.sh_flags = 1516 (ushort_t)(SOC_FC_HEADER | 1517 sf->sf_sochandle->fcal_portno); 1518 fpkt->fcal_socal_request.sr_soc_hdr.sh_class = 3; 1519 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_count = 1; 1520 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_flags = 0; 1521 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_seqno = 0; 1522 fpkt->fcal_socal_request.sr_dataseg[0].fc_base = 1523 (uint32_t)cmd->cmd_dmac; 1524 fpkt->fcal_socal_request.sr_dataseg[0].fc_count = 1525 sizeof (struct fcp_cmd); 1526 fpkt->fcal_socal_request.sr_dataseg[1].fc_base = 1527 (uint32_t)cmd->cmd_rsp_dmac; 1528 fpkt->fcal_socal_request.sr_dataseg[1].fc_count = 1529 FCP_MAX_RSP_IU_SIZE; 1530 1531 /* Fill in the Fabric Channel Header */ 1532 hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr; 1533 hp->r_ctl = R_CTL_COMMAND; 1534 hp->type = TYPE_SCSI_FCP; 1535 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 1536 hp->reserved1 = 0; 1537 hp->seq_id = 0; 1538 hp->df_ctl = 0; 1539 hp->seq_cnt = 0; 1540 hp->ox_id = 0xffff; 1541 hp->rx_id = 0xffff; 1542 hp->ro = 0; 1543 1544 /* Establish the LUN */ 1545 bcopy((caddr_t)&target->sft_lun.b, 1546 (caddr_t)&cmd->cmd_block->fcp_ent_addr, 1547 FCP_LUN_SIZE); 1548 *((int32_t *)&cmd->cmd_block->fcp_cntl) = 0; 1549 } 1550 cmd->cmd_pkt->pkt_cdbp = cmd->cmd_block->fcp_cdb; 1551 1552 mutex_enter(&target->sft_pkt_mutex); 1553 1554 target->sft_pkt_tail->cmd_forw = cmd; 1555 cmd->cmd_back = target->sft_pkt_tail; 1556 cmd->cmd_forw = (struct sf_pkt *)&target->sft_pkt_head; 1557 target->sft_pkt_tail = cmd; 1558 1559 mutex_exit(&target->sft_pkt_mutex); 1560 new_cmd = cmd; /* for later cleanup if needed */ 1561 } else { 1562 /* pkt already exists -- just a request for DMA allocation */ 1563 cmd = PKT2CMD(pkt); 1564 fpkt = cmd->cmd_fp_pkt; 1565 } 1566 1567 /* zero cdb (bzero is too slow) */ 1568 bzero((caddr_t)cmd->cmd_pkt->pkt_cdbp, cmdlen); 1569 1570 /* 1571 * Second step of sf_scsi_init_pkt: dma allocation 1572 * Set up dma info 1573 */ 1574 if ((bp != NULL) && (bp->b_bcount != 0)) { 1575 int cmd_flags, dma_flags; 1576 int rval = 0; 1577 uint_t dmacookie_count; 1578 1579 /* there is a buffer and some data to transfer */ 1580 1581 /* set up command and DMA flags */ 1582 cmd_flags = cmd->cmd_flags; 1583 if (bp->b_flags & B_READ) { 1584 /* a read */ 1585 cmd_flags &= ~CFLAG_DMASEND; 1586 dma_flags = DDI_DMA_READ; 1587 } else { 1588 /* a write */ 1589 cmd_flags |= CFLAG_DMASEND; 1590 dma_flags = DDI_DMA_WRITE; 1591 } 1592 if (flags & PKT_CONSISTENT) { 1593 cmd_flags |= CFLAG_CMDIOPB; 1594 dma_flags |= DDI_DMA_CONSISTENT; 1595 } 1596 1597 /* ensure we have a DMA handle */ 1598 if (cmd->cmd_dmahandle == NULL) { 1599 rval = ddi_dma_alloc_handle(sf->sf_dip, 1600 sf->sf_sochandle->fcal_dmaattr, callback, arg, 1601 &cmd->cmd_dmahandle); 1602 } 1603 1604 if (rval == 0) { 1605 /* bind our DMA handle to our buffer */ 1606 rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp, 1607 dma_flags, callback, arg, &cmd->cmd_dmacookie, 1608 &dmacookie_count); 1609 } 1610 1611 if (rval != 0) { 1612 /* DMA failure */ 1613 SF_DEBUG(2, (sf, CE_CONT, "ddi_dma_buf.. failed\n")); 1614 switch (rval) { 1615 case DDI_DMA_NORESOURCES: 1616 bioerror(bp, 0); 1617 break; 1618 case DDI_DMA_BADATTR: 1619 case DDI_DMA_NOMAPPING: 1620 bioerror(bp, EFAULT); 1621 break; 1622 case DDI_DMA_TOOBIG: 1623 default: 1624 bioerror(bp, EINVAL); 1625 break; 1626 } 1627 /* clear valid flag */ 1628 cmd->cmd_flags = cmd_flags & ~CFLAG_DMAVALID; 1629 if (new_cmd != NULL) { 1630 /* destroy packet if we just created it */ 1631 sf_scsi_destroy_pkt(ap, new_cmd->cmd_pkt); 1632 } 1633 return (NULL); 1634 } 1635 1636 ASSERT(dmacookie_count == 1); 1637 /* set up amt to transfer and set valid flag */ 1638 cmd->cmd_dmacount = bp->b_bcount; 1639 cmd->cmd_flags = cmd_flags | CFLAG_DMAVALID; 1640 1641 ASSERT(cmd->cmd_dmahandle != NULL); 1642 } 1643 1644 /* set up FC-AL packet */ 1645 fcmd = cmd->cmd_block; 1646 1647 if (cmd->cmd_flags & CFLAG_DMAVALID) { 1648 if (cmd->cmd_flags & CFLAG_DMASEND) { 1649 /* DMA write */ 1650 fcmd->fcp_cntl.cntl_read_data = 0; 1651 fcmd->fcp_cntl.cntl_write_data = 1; 1652 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = 1653 CQ_TYPE_IO_WRITE; 1654 } else { 1655 /* DMA read */ 1656 fcmd->fcp_cntl.cntl_read_data = 1; 1657 fcmd->fcp_cntl.cntl_write_data = 0; 1658 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = 1659 CQ_TYPE_IO_READ; 1660 } 1661 fpkt->fcal_socal_request.sr_dataseg[2].fc_base = 1662 (uint32_t)cmd->cmd_dmacookie.dmac_address; 1663 fpkt->fcal_socal_request.sr_dataseg[2].fc_count = 1664 cmd->cmd_dmacookie.dmac_size; 1665 fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3; 1666 fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = 1667 cmd->cmd_dmacookie.dmac_size; 1668 fcmd->fcp_data_len = cmd->cmd_dmacookie.dmac_size; 1669 } else { 1670 /* not a read or write */ 1671 fcmd->fcp_cntl.cntl_read_data = 0; 1672 fcmd->fcp_cntl.cntl_write_data = 0; 1673 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_SIMPLE; 1674 fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 2; 1675 fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = 1676 sizeof (struct fcp_cmd); 1677 fcmd->fcp_data_len = 0; 1678 } 1679 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 1680 1681 return (cmd->cmd_pkt); 1682 } 1683 1684 1685 /* 1686 * destroy a SCSI packet -- called internally and by the transport 1687 */ 1688 static void 1689 sf_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 1690 { 1691 struct sf_pkt *cmd = PKT2CMD(pkt); 1692 struct sf *sf = ADDR2SF(ap); 1693 struct sf_target *target = ADDR2TARGET(ap); 1694 struct fcal_packet *fpkt = cmd->cmd_fp_pkt; 1695 1696 1697 if (cmd->cmd_flags & CFLAG_DMAVALID) { 1698 /* DMA was set up -- clean up */ 1699 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle); 1700 cmd->cmd_flags ^= CFLAG_DMAVALID; 1701 } 1702 1703 /* take this packet off the doubly-linked list */ 1704 mutex_enter(&target->sft_pkt_mutex); 1705 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 1706 cmd->cmd_forw->cmd_back = cmd->cmd_back; 1707 mutex_exit(&target->sft_pkt_mutex); 1708 1709 fpkt->fcal_pkt_flags = 0; 1710 /* free the packet */ 1711 if ((cmd->cmd_flags & 1712 (CFLAG_FREE | CFLAG_PRIVEXTERN | CFLAG_SCBEXTERN)) == 0) { 1713 /* just a regular packet */ 1714 ASSERT(cmd->cmd_state != SF_STATE_ISSUED); 1715 cmd->cmd_flags = CFLAG_FREE; 1716 kmem_cache_free(sf->sf_pkt_cache, (void *)cmd); 1717 } else { 1718 /* a packet with extra memory */ 1719 sf_pkt_destroy_extern(sf, cmd); 1720 } 1721 } 1722 1723 1724 /* 1725 * called by transport to unbind DMA handle 1726 */ 1727 /* ARGSUSED */ 1728 static void 1729 sf_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 1730 { 1731 struct sf_pkt *cmd = PKT2CMD(pkt); 1732 1733 1734 if (cmd->cmd_flags & CFLAG_DMAVALID) { 1735 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle); 1736 cmd->cmd_flags ^= CFLAG_DMAVALID; 1737 } 1738 1739 } 1740 1741 1742 /* 1743 * called by transport to synchronize CPU and I/O views of memory 1744 */ 1745 /* ARGSUSED */ 1746 static void 1747 sf_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 1748 { 1749 struct sf_pkt *cmd = PKT2CMD(pkt); 1750 1751 1752 if (cmd->cmd_flags & CFLAG_DMAVALID) { 1753 if (ddi_dma_sync(cmd->cmd_dmahandle, (off_t)0, (size_t)0, 1754 (cmd->cmd_flags & CFLAG_DMASEND) ? 1755 DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU) != 1756 DDI_SUCCESS) { 1757 cmn_err(CE_WARN, "sf: sync pkt failed"); 1758 } 1759 } 1760 } 1761 1762 1763 /* 1764 * routine for reset notification setup, to register or cancel. -- called 1765 * by transport 1766 */ 1767 static int 1768 sf_scsi_reset_notify(struct scsi_address *ap, int flag, 1769 void (*callback)(caddr_t), caddr_t arg) 1770 { 1771 struct sf *sf = ADDR2SF(ap); 1772 1773 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 1774 &sf->sf_mutex, &sf->sf_reset_notify_listf)); 1775 } 1776 1777 1778 /* 1779 * called by transport to get port WWN property (except sun4u) 1780 */ 1781 /* ARGSUSED */ 1782 static int 1783 sf_scsi_get_name(struct scsi_device *sd, char *name, int len) 1784 { 1785 char tbuf[(FC_WWN_SIZE*2)+1]; 1786 unsigned char wwn[FC_WWN_SIZE]; 1787 int i, lun; 1788 dev_info_t *tgt_dip; 1789 1790 tgt_dip = sd->sd_dev; 1791 i = sizeof (wwn); 1792 if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF, 1793 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, PORT_WWN_PROP, 1794 (caddr_t)&wwn, &i) != DDI_SUCCESS) { 1795 name[0] = '\0'; 1796 return (0); 1797 } 1798 i = sizeof (lun); 1799 if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF, 1800 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun", 1801 (caddr_t)&lun, &i) != DDI_SUCCESS) { 1802 name[0] = '\0'; 1803 return (0); 1804 } 1805 for (i = 0; i < FC_WWN_SIZE; i++) 1806 (void) sprintf(&tbuf[i << 1], "%02x", wwn[i]); 1807 (void) sprintf(name, "w%s,%x", tbuf, lun); 1808 return (1); 1809 } 1810 1811 1812 /* 1813 * called by transport to get target soft AL-PA (except sun4u) 1814 */ 1815 /* ARGSUSED */ 1816 static int 1817 sf_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 1818 { 1819 struct sf_target *target = ADDR2TARGET(&sd->sd_address); 1820 1821 if (target == NULL) 1822 return (0); 1823 1824 (void) sprintf(name, "%x", target->sft_al_pa); 1825 return (1); 1826 } 1827 1828 1829 /* 1830 * add to the command/response buffer pool for this sf instance 1831 */ 1832 static int 1833 sf_add_cr_pool(struct sf *sf) 1834 { 1835 int cmd_buf_size; 1836 size_t real_cmd_buf_size; 1837 int rsp_buf_size; 1838 size_t real_rsp_buf_size; 1839 uint_t i, ccount; 1840 struct sf_cr_pool *ptr; 1841 struct sf_cr_free_elem *cptr; 1842 caddr_t dptr, eptr; 1843 ddi_dma_cookie_t cmd_cookie; 1844 ddi_dma_cookie_t rsp_cookie; 1845 int cmd_bound = FALSE, rsp_bound = FALSE; 1846 1847 1848 /* allocate room for the pool */ 1849 if ((ptr = kmem_zalloc(sizeof (struct sf_cr_pool), KM_NOSLEEP)) == 1850 NULL) { 1851 return (DDI_FAILURE); 1852 } 1853 1854 /* allocate a DMA handle for the command pool */ 1855 if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr, 1856 DDI_DMA_DONTWAIT, NULL, &ptr->cmd_dma_handle) != DDI_SUCCESS) { 1857 goto fail; 1858 } 1859 1860 /* 1861 * Get a piece of memory in which to put commands 1862 */ 1863 cmd_buf_size = (sizeof (struct fcp_cmd) * SF_ELEMS_IN_POOL + 7) & ~7; 1864 if (ddi_dma_mem_alloc(ptr->cmd_dma_handle, cmd_buf_size, 1865 sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT, 1866 DDI_DMA_DONTWAIT, NULL, (caddr_t *)&ptr->cmd_base, 1867 &real_cmd_buf_size, &ptr->cmd_acc_handle) != DDI_SUCCESS) { 1868 goto fail; 1869 } 1870 1871 /* bind the DMA handle to an address */ 1872 if (ddi_dma_addr_bind_handle(ptr->cmd_dma_handle, NULL, 1873 ptr->cmd_base, real_cmd_buf_size, 1874 DDI_DMA_WRITE | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 1875 NULL, &cmd_cookie, &ccount) != DDI_DMA_MAPPED) { 1876 goto fail; 1877 } 1878 cmd_bound = TRUE; 1879 /* ensure only one cookie was allocated */ 1880 if (ccount != 1) { 1881 goto fail; 1882 } 1883 1884 /* allocate a DMA handle for the response pool */ 1885 if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr, 1886 DDI_DMA_DONTWAIT, NULL, &ptr->rsp_dma_handle) != DDI_SUCCESS) { 1887 goto fail; 1888 } 1889 1890 /* 1891 * Get a piece of memory in which to put responses 1892 */ 1893 rsp_buf_size = FCP_MAX_RSP_IU_SIZE * SF_ELEMS_IN_POOL; 1894 if (ddi_dma_mem_alloc(ptr->rsp_dma_handle, rsp_buf_size, 1895 sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT, 1896 DDI_DMA_DONTWAIT, NULL, (caddr_t *)&ptr->rsp_base, 1897 &real_rsp_buf_size, &ptr->rsp_acc_handle) != DDI_SUCCESS) { 1898 goto fail; 1899 } 1900 1901 /* bind the DMA handle to an address */ 1902 if (ddi_dma_addr_bind_handle(ptr->rsp_dma_handle, NULL, 1903 ptr->rsp_base, real_rsp_buf_size, 1904 DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 1905 NULL, &rsp_cookie, &ccount) != DDI_DMA_MAPPED) { 1906 goto fail; 1907 } 1908 rsp_bound = TRUE; 1909 /* ensure only one cookie was allocated */ 1910 if (ccount != 1) { 1911 goto fail; 1912 } 1913 1914 /* 1915 * Generate a (cmd/rsp structure) free list 1916 */ 1917 /* ensure ptr points to start of long word (8-byte block) */ 1918 dptr = (caddr_t)((uintptr_t)(ptr->cmd_base) + 7 & ~7); 1919 /* keep track of actual size after moving pointer */ 1920 real_cmd_buf_size -= (dptr - ptr->cmd_base); 1921 eptr = ptr->rsp_base; 1922 1923 /* set actual total number of entries */ 1924 ptr->ntot = min((real_cmd_buf_size / sizeof (struct fcp_cmd)), 1925 (real_rsp_buf_size / FCP_MAX_RSP_IU_SIZE)); 1926 ptr->nfree = ptr->ntot; 1927 ptr->free = (struct sf_cr_free_elem *)ptr->cmd_base; 1928 ptr->sf = sf; 1929 1930 /* set up DMA for each pair of entries */ 1931 i = 0; 1932 while (i < ptr->ntot) { 1933 cptr = (struct sf_cr_free_elem *)dptr; 1934 dptr += sizeof (struct fcp_cmd); 1935 1936 cptr->next = (struct sf_cr_free_elem *)dptr; 1937 cptr->rsp = eptr; 1938 1939 cptr->cmd_dmac = cmd_cookie.dmac_address + 1940 (uint32_t)((caddr_t)cptr - ptr->cmd_base); 1941 1942 cptr->rsp_dmac = rsp_cookie.dmac_address + 1943 (uint32_t)((caddr_t)eptr - ptr->rsp_base); 1944 1945 eptr += FCP_MAX_RSP_IU_SIZE; 1946 i++; 1947 } 1948 1949 /* terminate the list */ 1950 cptr->next = NULL; 1951 1952 /* add this list at front of current one */ 1953 mutex_enter(&sf->sf_cr_mutex); 1954 ptr->next = sf->sf_cr_pool; 1955 sf->sf_cr_pool = ptr; 1956 sf->sf_cr_pool_cnt++; 1957 mutex_exit(&sf->sf_cr_mutex); 1958 1959 return (DDI_SUCCESS); 1960 1961 fail: 1962 /* we failed so clean up */ 1963 if (ptr->cmd_dma_handle != NULL) { 1964 if (cmd_bound) { 1965 (void) ddi_dma_unbind_handle(ptr->cmd_dma_handle); 1966 } 1967 ddi_dma_free_handle(&ptr->cmd_dma_handle); 1968 } 1969 1970 if (ptr->rsp_dma_handle != NULL) { 1971 if (rsp_bound) { 1972 (void) ddi_dma_unbind_handle(ptr->rsp_dma_handle); 1973 } 1974 ddi_dma_free_handle(&ptr->rsp_dma_handle); 1975 } 1976 1977 if (ptr->cmd_base != NULL) { 1978 ddi_dma_mem_free(&ptr->cmd_acc_handle); 1979 } 1980 1981 if (ptr->rsp_base != NULL) { 1982 ddi_dma_mem_free(&ptr->rsp_acc_handle); 1983 } 1984 1985 kmem_free((caddr_t)ptr, sizeof (struct sf_cr_pool)); 1986 return (DDI_FAILURE); 1987 } 1988 1989 1990 /* 1991 * allocate a command/response buffer from the pool, allocating more 1992 * in the pool as needed 1993 */ 1994 static int 1995 sf_cr_alloc(struct sf *sf, struct sf_pkt *cmd, int (*func)()) 1996 { 1997 struct sf_cr_pool *ptr; 1998 struct sf_cr_free_elem *cptr; 1999 2000 2001 mutex_enter(&sf->sf_cr_mutex); 2002 2003 try_again: 2004 2005 /* find a free buffer in the existing pool */ 2006 ptr = sf->sf_cr_pool; 2007 while (ptr != NULL) { 2008 if (ptr->nfree != 0) { 2009 ptr->nfree--; 2010 break; 2011 } else { 2012 ptr = ptr->next; 2013 } 2014 } 2015 2016 /* did we find a free buffer ? */ 2017 if (ptr != NULL) { 2018 /* we found a free buffer -- take it off the free list */ 2019 cptr = ptr->free; 2020 ptr->free = cptr->next; 2021 mutex_exit(&sf->sf_cr_mutex); 2022 /* set up the command to use the buffer pair */ 2023 cmd->cmd_block = (struct fcp_cmd *)cptr; 2024 cmd->cmd_dmac = cptr->cmd_dmac; 2025 cmd->cmd_rsp_dmac = cptr->rsp_dmac; 2026 cmd->cmd_rsp_block = (struct fcp_rsp *)cptr->rsp; 2027 cmd->cmd_cr_pool = ptr; 2028 return (DDI_SUCCESS); /* success */ 2029 } 2030 2031 /* no free buffer available -- can we allocate more ? */ 2032 if (sf->sf_cr_pool_cnt < SF_CR_POOL_MAX) { 2033 /* we need to allocate more buffer pairs */ 2034 if (sf->sf_cr_flag) { 2035 /* somebody already allocating for this instance */ 2036 if (func == SLEEP_FUNC) { 2037 /* user wants to wait */ 2038 cv_wait(&sf->sf_cr_cv, &sf->sf_cr_mutex); 2039 /* we've been woken so go try again */ 2040 goto try_again; 2041 } 2042 /* user does not want to wait */ 2043 mutex_exit(&sf->sf_cr_mutex); 2044 sf->sf_stats.cralloc_failures++; 2045 return (DDI_FAILURE); /* give up */ 2046 } 2047 /* set flag saying we're allocating */ 2048 sf->sf_cr_flag = 1; 2049 mutex_exit(&sf->sf_cr_mutex); 2050 /* add to our pool */ 2051 if (sf_add_cr_pool(sf) != DDI_SUCCESS) { 2052 /* couldn't add to our pool for some reason */ 2053 mutex_enter(&sf->sf_cr_mutex); 2054 sf->sf_cr_flag = 0; 2055 cv_broadcast(&sf->sf_cr_cv); 2056 mutex_exit(&sf->sf_cr_mutex); 2057 sf->sf_stats.cralloc_failures++; 2058 return (DDI_FAILURE); /* give up */ 2059 } 2060 /* 2061 * clear flag saying we're allocating and tell all other 2062 * that care 2063 */ 2064 mutex_enter(&sf->sf_cr_mutex); 2065 sf->sf_cr_flag = 0; 2066 cv_broadcast(&sf->sf_cr_cv); 2067 /* now that we have more buffers try again */ 2068 goto try_again; 2069 } 2070 2071 /* we don't have room to allocate any more buffers */ 2072 mutex_exit(&sf->sf_cr_mutex); 2073 sf->sf_stats.cralloc_failures++; 2074 return (DDI_FAILURE); /* give up */ 2075 } 2076 2077 2078 /* 2079 * free a cmd/response buffer pair in our pool 2080 */ 2081 static void 2082 sf_cr_free(struct sf_cr_pool *cp, struct sf_pkt *cmd) 2083 { 2084 struct sf *sf = cp->sf; 2085 struct sf_cr_free_elem *elem; 2086 2087 elem = (struct sf_cr_free_elem *)cmd->cmd_block; 2088 elem->rsp = (caddr_t)cmd->cmd_rsp_block; 2089 elem->cmd_dmac = cmd->cmd_dmac; 2090 elem->rsp_dmac = cmd->cmd_rsp_dmac; 2091 2092 mutex_enter(&sf->sf_cr_mutex); 2093 cp->nfree++; 2094 ASSERT(cp->nfree <= cp->ntot); 2095 2096 elem->next = cp->free; 2097 cp->free = elem; 2098 mutex_exit(&sf->sf_cr_mutex); 2099 } 2100 2101 2102 /* 2103 * free our pool of cmd/response buffers 2104 */ 2105 static void 2106 sf_crpool_free(struct sf *sf) 2107 { 2108 struct sf_cr_pool *cp, *prev; 2109 2110 prev = NULL; 2111 mutex_enter(&sf->sf_cr_mutex); 2112 cp = sf->sf_cr_pool; 2113 while (cp != NULL) { 2114 if (cp->nfree == cp->ntot) { 2115 if (prev != NULL) { 2116 prev->next = cp->next; 2117 } else { 2118 sf->sf_cr_pool = cp->next; 2119 } 2120 sf->sf_cr_pool_cnt--; 2121 mutex_exit(&sf->sf_cr_mutex); 2122 2123 (void) ddi_dma_unbind_handle(cp->cmd_dma_handle); 2124 ddi_dma_free_handle(&cp->cmd_dma_handle); 2125 (void) ddi_dma_unbind_handle(cp->rsp_dma_handle); 2126 ddi_dma_free_handle(&cp->rsp_dma_handle); 2127 ddi_dma_mem_free(&cp->cmd_acc_handle); 2128 ddi_dma_mem_free(&cp->rsp_acc_handle); 2129 kmem_free((caddr_t)cp, sizeof (struct sf_cr_pool)); 2130 return; 2131 } 2132 prev = cp; 2133 cp = cp->next; 2134 } 2135 mutex_exit(&sf->sf_cr_mutex); 2136 } 2137 2138 2139 /* ARGSUSED */ 2140 static int 2141 sf_kmem_cache_constructor(void *buf, void *arg, int size) 2142 { 2143 struct sf_pkt *cmd = buf; 2144 2145 mutex_init(&cmd->cmd_abort_mutex, NULL, MUTEX_DRIVER, NULL); 2146 cmd->cmd_block = NULL; 2147 cmd->cmd_dmahandle = NULL; 2148 return (0); 2149 } 2150 2151 2152 /* ARGSUSED */ 2153 static void 2154 sf_kmem_cache_destructor(void *buf, void *size) 2155 { 2156 struct sf_pkt *cmd = buf; 2157 2158 if (cmd->cmd_dmahandle != NULL) { 2159 ddi_dma_free_handle(&cmd->cmd_dmahandle); 2160 } 2161 2162 if (cmd->cmd_block != NULL) { 2163 sf_cr_free(cmd->cmd_cr_pool, cmd); 2164 } 2165 mutex_destroy(&cmd->cmd_abort_mutex); 2166 } 2167 2168 2169 /* 2170 * called by transport when a state change occurs 2171 */ 2172 static void 2173 sf_statec_callback(void *arg, int msg) 2174 { 2175 struct sf *sf = (struct sf *)arg; 2176 struct sf_target *target; 2177 int i; 2178 struct sf_pkt *cmd; 2179 struct scsi_pkt *pkt; 2180 2181 2182 2183 switch (msg) { 2184 2185 case FCAL_STATUS_LOOP_ONLINE: { 2186 uchar_t al_pa; /* to save AL-PA */ 2187 int ret; /* ret value from getmap */ 2188 int lip_cnt; /* to save current count */ 2189 int cnt; /* map length */ 2190 2191 /* 2192 * the loop has gone online 2193 */ 2194 SF_DEBUG(1, (sf, CE_CONT, "sf%d: loop online\n", 2195 ddi_get_instance(sf->sf_dip))); 2196 mutex_enter(&sf->sf_mutex); 2197 sf->sf_lip_cnt++; 2198 sf->sf_state = SF_STATE_ONLINING; 2199 mutex_exit(&sf->sf_mutex); 2200 2201 /* scan each target hash queue */ 2202 for (i = 0; i < SF_NUM_HASH_QUEUES; i++) { 2203 target = sf->sf_wwn_lists[i]; 2204 while (target != NULL) { 2205 /* 2206 * foreach target, if it's not offline then 2207 * mark it as busy 2208 */ 2209 mutex_enter(&target->sft_mutex); 2210 if (!(target->sft_state & SF_TARGET_OFFLINE)) 2211 target->sft_state |= (SF_TARGET_BUSY 2212 | SF_TARGET_MARK); 2213 #ifdef DEBUG 2214 /* 2215 * for debugging, print out info on any 2216 * pending commands (left hanging) 2217 */ 2218 cmd = target->sft_pkt_head; 2219 while (cmd != (struct sf_pkt *)&target-> 2220 sft_pkt_head) { 2221 if (cmd->cmd_state == 2222 SF_STATE_ISSUED) { 2223 SF_DEBUG(1, (sf, CE_CONT, 2224 "cmd 0x%p pending " 2225 "after lip\n", 2226 (void *)cmd->cmd_fp_pkt)); 2227 } 2228 cmd = cmd->cmd_forw; 2229 } 2230 #endif 2231 mutex_exit(&target->sft_mutex); 2232 target = target->sft_next; 2233 } 2234 } 2235 2236 /* 2237 * since the loop has just gone online get a new map from 2238 * the transport 2239 */ 2240 if ((ret = soc_get_lilp_map(sf->sf_sochandle, sf->sf_socp, 2241 sf->sf_sochandle->fcal_portno, (uint32_t)sf-> 2242 sf_lilp_dmacookie.dmac_address, 1)) != FCAL_SUCCESS) { 2243 if (sf_core && (sf_core & SF_CORE_LILP_FAILED)) { 2244 (void) soc_take_core(sf->sf_sochandle, 2245 sf->sf_socp); 2246 sf_core = 0; 2247 } 2248 sf_log(sf, CE_WARN, 2249 "!soc lilp map failed status=0x%x\n", ret); 2250 mutex_enter(&sf->sf_mutex); 2251 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT; 2252 sf->sf_lip_cnt++; 2253 sf->sf_state = SF_STATE_OFFLINE; 2254 mutex_exit(&sf->sf_mutex); 2255 return; 2256 } 2257 2258 /* ensure consistent view of DMA memory */ 2259 (void) ddi_dma_sync(sf->sf_lilp_dmahandle, (off_t)0, (size_t)0, 2260 DDI_DMA_SYNC_FORKERNEL); 2261 2262 /* how many entries in map ? */ 2263 cnt = sf->sf_lilp_map->lilp_length; 2264 if (cnt >= SF_MAX_LILP_ENTRIES) { 2265 sf_log(sf, CE_WARN, "invalid lilp map\n"); 2266 return; 2267 } 2268 2269 mutex_enter(&sf->sf_mutex); 2270 sf->sf_device_count = cnt - 1; 2271 sf->sf_al_pa = sf->sf_lilp_map->lilp_myalpa; 2272 lip_cnt = sf->sf_lip_cnt; 2273 al_pa = sf->sf_al_pa; 2274 2275 SF_DEBUG(1, (sf, CE_CONT, 2276 "!lilp map has %d entries, al_pa is %x\n", cnt, al_pa)); 2277 2278 /* 2279 * since the last entry of the map may be mine (common) check 2280 * for that, and if it is we have one less entry to look at 2281 */ 2282 if (sf->sf_lilp_map->lilp_alpalist[cnt-1] == al_pa) { 2283 cnt--; 2284 } 2285 /* If we didn't get a valid loop map enable all targets */ 2286 if (sf->sf_lilp_map->lilp_magic == FCAL_BADLILP_MAGIC) { 2287 for (i = 0; i < sizeof (sf_switch_to_alpa); i++) 2288 sf->sf_lilp_map->lilp_alpalist[i] = 2289 sf_switch_to_alpa[i]; 2290 cnt = i; 2291 sf->sf_device_count = cnt - 1; 2292 } 2293 if (sf->sf_device_count == 0) { 2294 sf_finish_init(sf, lip_cnt); 2295 mutex_exit(&sf->sf_mutex); 2296 break; 2297 } 2298 mutex_exit(&sf->sf_mutex); 2299 2300 SF_DEBUG(2, (sf, CE_WARN, 2301 "!statec_callback: starting with %d targets\n", 2302 sf->sf_device_count)); 2303 2304 /* scan loop map, logging into all ports (except mine) */ 2305 for (i = 0; i < cnt; i++) { 2306 SF_DEBUG(1, (sf, CE_CONT, 2307 "!lilp map entry %d = %x,%x\n", i, 2308 sf->sf_lilp_map->lilp_alpalist[i], 2309 sf_alpa_to_switch[ 2310 sf->sf_lilp_map->lilp_alpalist[i]])); 2311 /* is this entry for somebody else ? */ 2312 if (sf->sf_lilp_map->lilp_alpalist[i] != al_pa) { 2313 /* do a PLOGI to this port */ 2314 if (!sf_login(sf, LA_ELS_PLOGI, 2315 sf->sf_lilp_map->lilp_alpalist[i], 2316 sf->sf_lilp_map->lilp_alpalist[cnt-1], 2317 lip_cnt)) { 2318 /* a problem logging in */ 2319 mutex_enter(&sf->sf_mutex); 2320 if (lip_cnt == sf->sf_lip_cnt) { 2321 /* 2322 * problem not from a new LIP 2323 */ 2324 sf->sf_device_count--; 2325 ASSERT(sf->sf_device_count 2326 >= 0); 2327 if (sf->sf_device_count == 0) { 2328 sf_finish_init(sf, 2329 lip_cnt); 2330 } 2331 } 2332 mutex_exit(&sf->sf_mutex); 2333 } 2334 } 2335 } 2336 break; 2337 } 2338 2339 case FCAL_STATUS_ERR_OFFLINE: 2340 /* 2341 * loop has gone offline due to an error 2342 */ 2343 SF_DEBUG(1, (sf, CE_CONT, "sf%d: loop offline\n", 2344 ddi_get_instance(sf->sf_dip))); 2345 mutex_enter(&sf->sf_mutex); 2346 sf->sf_lip_cnt++; 2347 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT; 2348 if (!sf->sf_online_timer) { 2349 sf->sf_online_timer = sf_watchdog_time + 2350 SF_ONLINE_TIMEOUT; 2351 } 2352 /* 2353 * if we are suspended, preserve the SF_STATE_SUSPENDED flag, 2354 * since throttling logic in sf_watch() depends on 2355 * preservation of this flag while device is suspended 2356 */ 2357 if (sf->sf_state & SF_STATE_SUSPENDED) { 2358 sf->sf_state |= SF_STATE_OFFLINE; 2359 SF_DEBUG(1, (sf, CE_CONT, 2360 "sf_statec_callback, sf%d: " 2361 "got FCAL_STATE_OFFLINE during DDI_SUSPEND\n", 2362 ddi_get_instance(sf->sf_dip))); 2363 } else { 2364 sf->sf_state = SF_STATE_OFFLINE; 2365 } 2366 2367 /* scan each possible target on the loop */ 2368 for (i = 0; i < sf_max_targets; i++) { 2369 target = sf->sf_targets[i]; 2370 while (target != NULL) { 2371 mutex_enter(&target->sft_mutex); 2372 if (!(target->sft_state & SF_TARGET_OFFLINE)) 2373 target->sft_state |= (SF_TARGET_BUSY 2374 | SF_TARGET_MARK); 2375 mutex_exit(&target->sft_mutex); 2376 target = target->sft_next_lun; 2377 } 2378 } 2379 mutex_exit(&sf->sf_mutex); 2380 break; 2381 2382 case FCAL_STATE_RESET: { 2383 struct sf_els_hdr *privp; /* ptr to private list */ 2384 struct sf_els_hdr *tmpp1; /* tmp prev hdr ptr */ 2385 struct sf_els_hdr *tmpp2; /* tmp next hdr ptr */ 2386 struct sf_els_hdr *head; /* to save our private list */ 2387 struct fcal_packet *fpkt; /* ptr to pkt in hdr */ 2388 2389 /* 2390 * a transport reset 2391 */ 2392 SF_DEBUG(1, (sf, CE_CONT, "!sf%d: soc reset\n", 2393 ddi_get_instance(sf->sf_dip))); 2394 tmpp1 = head = NULL; 2395 mutex_enter(&sf->sf_mutex); 2396 sf->sf_lip_cnt++; 2397 sf->sf_timer = sf_watchdog_time + SF_RESET_TIMEOUT; 2398 /* 2399 * if we are suspended, preserve the SF_STATE_SUSPENDED flag, 2400 * since throttling logic in sf_watch() depends on 2401 * preservation of this flag while device is suspended 2402 */ 2403 if (sf->sf_state & SF_STATE_SUSPENDED) { 2404 sf->sf_state |= SF_STATE_OFFLINE; 2405 SF_DEBUG(1, (sf, CE_CONT, 2406 "sf_statec_callback, sf%d: " 2407 "got FCAL_STATE_RESET during DDI_SUSPEND\n", 2408 ddi_get_instance(sf->sf_dip))); 2409 } else { 2410 sf->sf_state = SF_STATE_OFFLINE; 2411 } 2412 2413 /* 2414 * scan each possible target on the loop, looking for targets 2415 * that need callbacks ran 2416 */ 2417 for (i = 0; i < sf_max_targets; i++) { 2418 target = sf->sf_targets[i]; 2419 while (target != NULL) { 2420 if (!(target->sft_state & SF_TARGET_OFFLINE)) { 2421 target->sft_state |= (SF_TARGET_BUSY 2422 | SF_TARGET_MARK); 2423 mutex_exit(&sf->sf_mutex); 2424 /* 2425 * run remove event callbacks for lun 2426 * 2427 * We have a nasty race condition here 2428 * 'cause we're dropping this mutex to 2429 * run the callback and expect the 2430 * linked list to be the same. 2431 */ 2432 (void) ndi_event_retrieve_cookie( 2433 sf->sf_event_hdl, target->sft_dip, 2434 FCAL_REMOVE_EVENT, &sf_remove_eid, 2435 NDI_EVENT_NOPASS); 2436 (void) ndi_event_run_callbacks( 2437 sf->sf_event_hdl, 2438 target->sft_dip, 2439 sf_remove_eid, NULL); 2440 mutex_enter(&sf->sf_mutex); 2441 } 2442 target = target->sft_next_lun; 2443 } 2444 } 2445 2446 /* 2447 * scan for ELS commands that are in transport, not complete, 2448 * and have a valid timeout, building a private list 2449 */ 2450 privp = sf->sf_els_list; 2451 while (privp != NULL) { 2452 fpkt = privp->fpkt; 2453 if ((fpkt->fcal_cmd_state & FCAL_CMD_IN_TRANSPORT) && 2454 (!(fpkt->fcal_cmd_state & FCAL_CMD_COMPLETE)) && 2455 (privp->timeout != SF_INVALID_TIMEOUT)) { 2456 /* 2457 * cmd in transport && not complete && 2458 * timeout valid 2459 * 2460 * move this entry from ELS input list to our 2461 * private list 2462 */ 2463 2464 tmpp2 = privp->next; /* save ptr to next */ 2465 2466 /* push this on private list head */ 2467 privp->next = head; 2468 head = privp; 2469 2470 /* remove this entry from input list */ 2471 if (tmpp1 != NULL) { 2472 /* 2473 * remove this entry from somewhere in 2474 * the middle of the list 2475 */ 2476 tmpp1->next = tmpp2; 2477 if (tmpp2 != NULL) { 2478 tmpp2->prev = tmpp1; 2479 } 2480 } else { 2481 /* 2482 * remove this entry from the head 2483 * of the list 2484 */ 2485 sf->sf_els_list = tmpp2; 2486 if (tmpp2 != NULL) { 2487 tmpp2->prev = NULL; 2488 } 2489 } 2490 privp = tmpp2; /* skip to next entry */ 2491 } else { 2492 tmpp1 = privp; /* save ptr to prev entry */ 2493 privp = privp->next; /* skip to next entry */ 2494 } 2495 } 2496 2497 mutex_exit(&sf->sf_mutex); 2498 2499 /* 2500 * foreach cmd in our list free the ELS packet associated 2501 * with it 2502 */ 2503 privp = head; 2504 while (privp != NULL) { 2505 fpkt = privp->fpkt; 2506 privp = privp->next; 2507 sf_els_free(fpkt); 2508 } 2509 2510 /* 2511 * scan for commands from each possible target 2512 */ 2513 for (i = 0; i < sf_max_targets; i++) { 2514 target = sf->sf_targets[i]; 2515 while (target != NULL) { 2516 /* 2517 * scan all active commands for this target, 2518 * looking for commands that have been issued, 2519 * are in transport, and are not yet complete 2520 * (so we can terminate them because of the 2521 * reset) 2522 */ 2523 mutex_enter(&target->sft_pkt_mutex); 2524 cmd = target->sft_pkt_head; 2525 while (cmd != (struct sf_pkt *)&target-> 2526 sft_pkt_head) { 2527 fpkt = cmd->cmd_fp_pkt; 2528 mutex_enter(&cmd->cmd_abort_mutex); 2529 if ((cmd->cmd_state == 2530 SF_STATE_ISSUED) && 2531 (fpkt->fcal_cmd_state & 2532 FCAL_CMD_IN_TRANSPORT) && 2533 (!(fpkt->fcal_cmd_state & 2534 FCAL_CMD_COMPLETE))) { 2535 /* a command to be reset */ 2536 pkt = cmd->cmd_pkt; 2537 pkt->pkt_reason = CMD_RESET; 2538 pkt->pkt_statistics |= 2539 STAT_BUS_RESET; 2540 cmd->cmd_state = SF_STATE_IDLE; 2541 mutex_exit(&cmd-> 2542 cmd_abort_mutex); 2543 mutex_exit(&target-> 2544 sft_pkt_mutex); 2545 if (pkt->pkt_comp != NULL) { 2546 (*pkt->pkt_comp)(pkt); 2547 } 2548 mutex_enter(&target-> 2549 sft_pkt_mutex); 2550 cmd = target->sft_pkt_head; 2551 } else { 2552 mutex_exit(&cmd-> 2553 cmd_abort_mutex); 2554 /* get next command */ 2555 cmd = cmd->cmd_forw; 2556 } 2557 } 2558 mutex_exit(&target->sft_pkt_mutex); 2559 target = target->sft_next_lun; 2560 } 2561 } 2562 2563 /* 2564 * get packet queue for this target, resetting all remaining 2565 * commands 2566 */ 2567 mutex_enter(&sf->sf_mutex); 2568 cmd = sf->sf_pkt_head; 2569 sf->sf_pkt_head = NULL; 2570 mutex_exit(&sf->sf_mutex); 2571 2572 while (cmd != NULL) { 2573 pkt = cmd->cmd_pkt; 2574 cmd = cmd->cmd_next; 2575 pkt->pkt_reason = CMD_RESET; 2576 pkt->pkt_statistics |= STAT_BUS_RESET; 2577 if (pkt->pkt_comp != NULL) { 2578 (*pkt->pkt_comp)(pkt); 2579 } 2580 } 2581 break; 2582 } 2583 2584 default: 2585 break; 2586 } 2587 } 2588 2589 2590 /* 2591 * called to send a PLOGI (N_port login) ELS request to a destination ID, 2592 * returning TRUE upon success, else returning FALSE 2593 */ 2594 static int 2595 sf_login(struct sf *sf, uchar_t els_code, uchar_t dest_id, uint_t arg1, 2596 int lip_cnt) 2597 { 2598 struct la_els_logi *logi; 2599 struct sf_els_hdr *privp; 2600 2601 2602 if (sf_els_alloc(sf, dest_id, sizeof (struct sf_els_hdr), 2603 sizeof (union sf_els_cmd), sizeof (union sf_els_rsp), 2604 (caddr_t *)&privp, (caddr_t *)&logi) == NULL) { 2605 sf_log(sf, CE_WARN, "Cannot allocate PLOGI for target %x " 2606 "due to DVMA shortage.\n", sf_alpa_to_switch[dest_id]); 2607 return (FALSE); 2608 } 2609 2610 privp->lip_cnt = lip_cnt; 2611 if (els_code == LA_ELS_PLOGI) { 2612 bcopy((caddr_t)sf->sf_sochandle->fcal_loginparms, 2613 (caddr_t)&logi->common_service, sizeof (struct la_els_logi) 2614 - 4); 2615 bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn, 2616 (caddr_t)&logi->nport_ww_name, sizeof (la_wwn_t)); 2617 bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn, 2618 (caddr_t)&logi->node_ww_name, sizeof (la_wwn_t)); 2619 bzero((caddr_t)&logi->reserved, 16); 2620 } else if (els_code == LA_ELS_LOGO) { 2621 bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn, 2622 (caddr_t)&(((struct la_els_logo *)logi)->nport_ww_name), 8); 2623 ((struct la_els_logo *)logi)->reserved = 0; 2624 ((struct la_els_logo *)logi)->nport_id[0] = 0; 2625 ((struct la_els_logo *)logi)->nport_id[1] = 0; 2626 ((struct la_els_logo *)logi)->nport_id[2] = arg1; 2627 } 2628 2629 privp->els_code = els_code; 2630 logi->ls_code = els_code; 2631 logi->mbz[0] = 0; 2632 logi->mbz[1] = 0; 2633 logi->mbz[2] = 0; 2634 2635 privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT; 2636 return (sf_els_transport(sf, privp)); 2637 } 2638 2639 2640 /* 2641 * send an ELS IU via the transport, 2642 * returning TRUE upon success, else returning FALSE 2643 */ 2644 static int 2645 sf_els_transport(struct sf *sf, struct sf_els_hdr *privp) 2646 { 2647 struct fcal_packet *fpkt = privp->fpkt; 2648 2649 2650 (void) ddi_dma_sync(privp->cmd_dma_handle, (off_t)0, (size_t)0, 2651 DDI_DMA_SYNC_FORDEV); 2652 privp->prev = NULL; 2653 mutex_enter(&sf->sf_mutex); 2654 privp->next = sf->sf_els_list; 2655 if (sf->sf_els_list != NULL) { 2656 sf->sf_els_list->prev = privp; 2657 } 2658 sf->sf_els_list = privp; 2659 mutex_exit(&sf->sf_mutex); 2660 2661 /* call the transport to send a packet */ 2662 if (soc_transport(sf->sf_sochandle, fpkt, FCAL_NOSLEEP, 2663 CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) { 2664 mutex_enter(&sf->sf_mutex); 2665 if (privp->prev != NULL) { 2666 privp->prev->next = privp->next; 2667 } 2668 if (privp->next != NULL) { 2669 privp->next->prev = privp->prev; 2670 } 2671 if (sf->sf_els_list == privp) { 2672 sf->sf_els_list = privp->next; 2673 } 2674 mutex_exit(&sf->sf_mutex); 2675 sf_els_free(fpkt); 2676 return (FALSE); /* failure */ 2677 } 2678 return (TRUE); /* success */ 2679 } 2680 2681 2682 /* 2683 * called as the pkt_comp routine for ELS FC packets 2684 */ 2685 static void 2686 sf_els_callback(struct fcal_packet *fpkt) 2687 { 2688 struct sf_els_hdr *privp = fpkt->fcal_pkt_private; 2689 struct sf *sf = privp->sf; 2690 struct sf *tsf; 2691 int tgt_id; 2692 struct la_els_logi *ptr = (struct la_els_logi *)privp->rsp; 2693 struct la_els_adisc *adisc = (struct la_els_adisc *)ptr; 2694 struct sf_target *target; 2695 short ncmds; 2696 short free_pkt = TRUE; 2697 2698 2699 /* 2700 * we've received an ELS callback, i.e. an ELS packet has arrived 2701 */ 2702 2703 /* take the current packet off of the queue */ 2704 mutex_enter(&sf->sf_mutex); 2705 if (privp->timeout == SF_INVALID_TIMEOUT) { 2706 mutex_exit(&sf->sf_mutex); 2707 return; 2708 } 2709 if (privp->prev != NULL) { 2710 privp->prev->next = privp->next; 2711 } 2712 if (privp->next != NULL) { 2713 privp->next->prev = privp->prev; 2714 } 2715 if (sf->sf_els_list == privp) { 2716 sf->sf_els_list = privp->next; 2717 } 2718 privp->prev = privp->next = NULL; 2719 mutex_exit(&sf->sf_mutex); 2720 2721 /* get # pkts in this callback */ 2722 ncmds = fpkt->fcal_ncmds; 2723 ASSERT(ncmds >= 0); 2724 mutex_enter(&sf->sf_cmd_mutex); 2725 sf->sf_ncmds = ncmds; 2726 mutex_exit(&sf->sf_cmd_mutex); 2727 2728 /* sync idea of memory */ 2729 (void) ddi_dma_sync(privp->rsp_dma_handle, (off_t)0, (size_t)0, 2730 DDI_DMA_SYNC_FORKERNEL); 2731 2732 /* was this an OK ACC msg ?? */ 2733 if ((fpkt->fcal_pkt_status == FCAL_STATUS_OK) && 2734 (ptr->ls_code == LA_ELS_ACC)) { 2735 2736 /* 2737 * this was an OK ACC pkt 2738 */ 2739 2740 switch (privp->els_code) { 2741 case LA_ELS_PLOGI: 2742 /* 2743 * was able to to an N_port login 2744 */ 2745 SF_DEBUG(2, (sf, CE_CONT, 2746 "!PLOGI to al_pa %x succeeded, wwn %x%x\n", 2747 privp->dest_nport_id, 2748 *((int *)&ptr->nport_ww_name.raw_wwn[0]), 2749 *((int *)&ptr->nport_ww_name.raw_wwn[4]))); 2750 /* try to do a process login */ 2751 if (!sf_do_prli(sf, privp, ptr)) { 2752 free_pkt = FALSE; 2753 goto fail; /* PRLI failed */ 2754 } 2755 break; 2756 case LA_ELS_PRLI: 2757 /* 2758 * was able to do a process login 2759 */ 2760 SF_DEBUG(2, (sf, CE_CONT, 2761 "!PRLI to al_pa %x succeeded\n", 2762 privp->dest_nport_id)); 2763 /* try to do address discovery */ 2764 if (sf_do_adisc(sf, privp) != 1) { 2765 free_pkt = FALSE; 2766 goto fail; /* ADISC failed */ 2767 } 2768 break; 2769 case LA_ELS_ADISC: 2770 /* 2771 * found a target via ADISC 2772 */ 2773 2774 SF_DEBUG(2, (sf, CE_CONT, 2775 "!ADISC to al_pa %x succeeded\n", 2776 privp->dest_nport_id)); 2777 2778 /* create the target info */ 2779 if ((target = sf_create_target(sf, privp, 2780 sf_alpa_to_switch[(uchar_t)adisc->hard_address], 2781 (int64_t)0)) 2782 == NULL) { 2783 goto fail; /* can't create target */ 2784 } 2785 2786 /* 2787 * ensure address discovered matches what we thought 2788 * it would be 2789 */ 2790 if ((uchar_t)adisc->hard_address != 2791 privp->dest_nport_id) { 2792 sf_log(sf, CE_WARN, 2793 "target 0x%x, AL-PA 0x%x and " 2794 "hard address 0x%x don't match\n", 2795 sf_alpa_to_switch[ 2796 (uchar_t)privp->dest_nport_id], 2797 privp->dest_nport_id, 2798 (uchar_t)adisc->hard_address); 2799 mutex_enter(&sf->sf_mutex); 2800 sf_offline_target(sf, target); 2801 mutex_exit(&sf->sf_mutex); 2802 goto fail; /* addr doesn't match */ 2803 } 2804 /* 2805 * get inquiry data from the target 2806 */ 2807 if (!sf_do_reportlun(sf, privp, target)) { 2808 mutex_enter(&sf->sf_mutex); 2809 sf_offline_target(sf, target); 2810 mutex_exit(&sf->sf_mutex); 2811 free_pkt = FALSE; 2812 goto fail; /* inquiry failed */ 2813 } 2814 break; 2815 default: 2816 SF_DEBUG(2, (sf, CE_CONT, 2817 "!ELS %x to al_pa %x succeeded\n", 2818 privp->els_code, privp->dest_nport_id)); 2819 sf_els_free(fpkt); 2820 break; 2821 } 2822 2823 } else { 2824 2825 /* 2826 * oh oh -- this was not an OK ACC packet 2827 */ 2828 2829 /* get target ID from dest loop address */ 2830 tgt_id = sf_alpa_to_switch[(uchar_t)privp->dest_nport_id]; 2831 2832 /* keep track of failures */ 2833 sf->sf_stats.tstats[tgt_id].els_failures++; 2834 if (++(privp->retries) < sf_els_retries && 2835 fpkt->fcal_pkt_status != FCAL_STATUS_OPEN_FAIL) { 2836 if (fpkt->fcal_pkt_status == 2837 FCAL_STATUS_MAX_XCHG_EXCEEDED) { 2838 tsf = sf->sf_sibling; 2839 if (tsf != NULL) { 2840 mutex_enter(&tsf->sf_cmd_mutex); 2841 tsf->sf_flag = 1; 2842 tsf->sf_throttle = SF_DECR_DELTA; 2843 mutex_exit(&tsf->sf_cmd_mutex); 2844 } 2845 } 2846 privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT; 2847 privp->prev = NULL; 2848 2849 mutex_enter(&sf->sf_mutex); 2850 2851 if (privp->lip_cnt == sf->sf_lip_cnt) { 2852 SF_DEBUG(1, (sf, CE_WARN, 2853 "!ELS %x to al_pa %x failed, retrying", 2854 privp->els_code, privp->dest_nport_id)); 2855 privp->next = sf->sf_els_list; 2856 if (sf->sf_els_list != NULL) { 2857 sf->sf_els_list->prev = privp; 2858 } 2859 2860 sf->sf_els_list = privp; 2861 2862 mutex_exit(&sf->sf_mutex); 2863 /* device busy? wait a bit ... */ 2864 if (fpkt->fcal_pkt_status == 2865 FCAL_STATUS_MAX_XCHG_EXCEEDED) { 2866 privp->delayed_retry = 1; 2867 return; 2868 } 2869 /* call the transport to send a pkt */ 2870 if (soc_transport(sf->sf_sochandle, fpkt, 2871 FCAL_NOSLEEP, CQ_REQUEST_1) != 2872 FCAL_TRANSPORT_SUCCESS) { 2873 mutex_enter(&sf->sf_mutex); 2874 if (privp->prev != NULL) { 2875 privp->prev->next = 2876 privp->next; 2877 } 2878 if (privp->next != NULL) { 2879 privp->next->prev = 2880 privp->prev; 2881 } 2882 if (sf->sf_els_list == privp) { 2883 sf->sf_els_list = privp->next; 2884 } 2885 mutex_exit(&sf->sf_mutex); 2886 goto fail; 2887 } else 2888 return; 2889 } else { 2890 mutex_exit(&sf->sf_mutex); 2891 goto fail; 2892 } 2893 } else { 2894 #ifdef DEBUG 2895 if (fpkt->fcal_pkt_status != 0x36 || sfdebug > 4) { 2896 SF_DEBUG(2, (sf, CE_NOTE, "ELS %x to al_pa %x failed", 2897 privp->els_code, privp->dest_nport_id)); 2898 if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) { 2899 SF_DEBUG(2, (sf, CE_NOTE, 2900 "els reply code = %x", ptr->ls_code)); 2901 if (ptr->ls_code == LA_ELS_RJT) 2902 SF_DEBUG(1, (sf, CE_CONT, 2903 "LS_RJT reason = %x\n", 2904 *(((uint_t *)ptr) + 1))); 2905 } else 2906 SF_DEBUG(2, (sf, CE_NOTE, 2907 "fc packet status = %x", 2908 fpkt->fcal_pkt_status)); 2909 } 2910 #endif 2911 goto fail; 2912 } 2913 } 2914 return; /* success */ 2915 fail: 2916 mutex_enter(&sf->sf_mutex); 2917 if (sf->sf_lip_cnt == privp->lip_cnt) { 2918 sf->sf_device_count--; 2919 ASSERT(sf->sf_device_count >= 0); 2920 if (sf->sf_device_count == 0) { 2921 sf_finish_init(sf, privp->lip_cnt); 2922 } 2923 } 2924 mutex_exit(&sf->sf_mutex); 2925 if (free_pkt) { 2926 sf_els_free(fpkt); 2927 } 2928 } 2929 2930 2931 /* 2932 * send a PRLI (process login) ELS IU via the transport, 2933 * returning TRUE upon success, else returning FALSE 2934 */ 2935 static int 2936 sf_do_prli(struct sf *sf, struct sf_els_hdr *privp, struct la_els_logi *ptr) 2937 { 2938 struct la_els_prli *prli = (struct la_els_prli *)privp->cmd; 2939 struct fcp_prli *fprli; 2940 struct fcal_packet *fpkt = privp->fpkt; 2941 2942 2943 fpkt->fcal_socal_request.sr_dataseg[0].fc_count = 2944 sizeof (struct la_els_prli); 2945 privp->els_code = LA_ELS_PRLI; 2946 fprli = (struct fcp_prli *)prli->service_params; 2947 prli->ls_code = LA_ELS_PRLI; 2948 prli->page_length = 0x10; 2949 prli->payload_length = sizeof (struct la_els_prli); 2950 fprli->type = 0x08; /* no define here? */ 2951 fprli->resvd1 = 0; 2952 fprli->orig_process_assoc_valid = 0; 2953 fprli->resp_process_assoc_valid = 0; 2954 fprli->establish_image_pair = 1; 2955 fprli->resvd2 = 0; 2956 fprli->resvd3 = 0; 2957 fprli->data_overlay_allowed = 0; 2958 fprli->initiator_fn = 1; 2959 fprli->target_fn = 0; 2960 fprli->cmd_data_mixed = 0; 2961 fprli->data_resp_mixed = 0; 2962 fprli->read_xfer_rdy_disabled = 1; 2963 fprli->write_xfer_rdy_disabled = 0; 2964 2965 bcopy((caddr_t)&ptr->nport_ww_name, (caddr_t)&privp->port_wwn, 2966 sizeof (privp->port_wwn)); 2967 bcopy((caddr_t)&ptr->node_ww_name, (caddr_t)&privp->node_wwn, 2968 sizeof (privp->node_wwn)); 2969 2970 privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT; 2971 return (sf_els_transport(sf, privp)); 2972 } 2973 2974 2975 /* 2976 * send an ADISC (address discovery) ELS IU via the transport, 2977 * returning TRUE upon success, else returning FALSE 2978 */ 2979 static int 2980 sf_do_adisc(struct sf *sf, struct sf_els_hdr *privp) 2981 { 2982 struct la_els_adisc *adisc = (struct la_els_adisc *)privp->cmd; 2983 struct fcal_packet *fpkt = privp->fpkt; 2984 2985 privp->els_code = LA_ELS_ADISC; 2986 adisc->ls_code = LA_ELS_ADISC; 2987 adisc->mbz[0] = 0; 2988 adisc->mbz[1] = 0; 2989 adisc->mbz[2] = 0; 2990 adisc->hard_address = 0; /* ??? */ 2991 fpkt->fcal_socal_request.sr_dataseg[0].fc_count = 2992 sizeof (struct la_els_adisc); 2993 bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn, 2994 (caddr_t)&adisc->port_wwn, sizeof (adisc->port_wwn)); 2995 bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn, 2996 (caddr_t)&adisc->node_wwn, sizeof (adisc->node_wwn)); 2997 adisc->nport_id = sf->sf_al_pa; 2998 2999 privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT; 3000 return (sf_els_transport(sf, privp)); 3001 } 3002 3003 3004 static struct fcal_packet * 3005 sf_els_alloc(struct sf *sf, uchar_t dest_id, int priv_size, int cmd_size, 3006 int rsp_size, caddr_t *rprivp, caddr_t *cmd_buf) 3007 { 3008 struct fcal_packet *fpkt; 3009 ddi_dma_cookie_t pcookie; 3010 ddi_dma_cookie_t rcookie; 3011 struct sf_els_hdr *privp; 3012 ddi_dma_handle_t cmd_dma_handle = NULL; 3013 ddi_dma_handle_t rsp_dma_handle = NULL; 3014 ddi_acc_handle_t cmd_acc_handle = NULL; 3015 ddi_acc_handle_t rsp_acc_handle = NULL; 3016 size_t real_size; 3017 uint_t ccount; 3018 fc_frame_header_t *hp; 3019 int cmd_bound = FALSE, rsp_bound = FALSE; 3020 caddr_t cmd = NULL; 3021 caddr_t rsp = NULL; 3022 3023 if ((fpkt = (struct fcal_packet *)kmem_zalloc( 3024 sizeof (struct fcal_packet), KM_NOSLEEP)) == NULL) { 3025 SF_DEBUG(1, (sf, CE_WARN, 3026 "Could not allocate fcal_packet for ELS\n")); 3027 return (NULL); 3028 } 3029 3030 if ((privp = (struct sf_els_hdr *)kmem_zalloc(priv_size, 3031 KM_NOSLEEP)) == NULL) { 3032 SF_DEBUG(1, (sf, CE_WARN, 3033 "Could not allocate sf_els_hdr for ELS\n")); 3034 goto fail; 3035 } 3036 3037 privp->size = priv_size; 3038 fpkt->fcal_pkt_private = (caddr_t)privp; 3039 3040 if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr, 3041 DDI_DMA_DONTWAIT, NULL, &cmd_dma_handle) != DDI_SUCCESS) { 3042 SF_DEBUG(1, (sf, CE_WARN, 3043 "Could not allocate DMA handle for ELS\n")); 3044 goto fail; 3045 } 3046 3047 if (ddi_dma_mem_alloc(cmd_dma_handle, cmd_size, 3048 sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT, 3049 DDI_DMA_DONTWAIT, NULL, &cmd, 3050 &real_size, &cmd_acc_handle) != DDI_SUCCESS) { 3051 SF_DEBUG(1, (sf, CE_WARN, 3052 "Could not allocate DMA memory for ELS\n")); 3053 goto fail; 3054 } 3055 3056 if (real_size < cmd_size) { 3057 SF_DEBUG(1, (sf, CE_WARN, 3058 "DMA memory too small for ELS\n")); 3059 goto fail; 3060 } 3061 3062 if (ddi_dma_addr_bind_handle(cmd_dma_handle, NULL, 3063 cmd, real_size, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 3064 DDI_DMA_DONTWAIT, NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) { 3065 SF_DEBUG(1, (sf, CE_WARN, 3066 "Could not bind DMA memory for ELS\n")); 3067 goto fail; 3068 } 3069 cmd_bound = TRUE; 3070 3071 if (ccount != 1) { 3072 SF_DEBUG(1, (sf, CE_WARN, 3073 "Wrong cookie count for ELS\n")); 3074 goto fail; 3075 } 3076 3077 if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr, 3078 DDI_DMA_DONTWAIT, NULL, &rsp_dma_handle) != DDI_SUCCESS) { 3079 SF_DEBUG(1, (sf, CE_WARN, 3080 "Could not allocate DMA handle for ELS rsp\n")); 3081 goto fail; 3082 } 3083 if (ddi_dma_mem_alloc(rsp_dma_handle, rsp_size, 3084 sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT, 3085 DDI_DMA_DONTWAIT, NULL, &rsp, 3086 &real_size, &rsp_acc_handle) != DDI_SUCCESS) { 3087 SF_DEBUG(1, (sf, CE_WARN, 3088 "Could not allocate DMA memory for ELS rsp\n")); 3089 goto fail; 3090 } 3091 3092 if (real_size < rsp_size) { 3093 SF_DEBUG(1, (sf, CE_WARN, 3094 "DMA memory too small for ELS rsp\n")); 3095 goto fail; 3096 } 3097 3098 if (ddi_dma_addr_bind_handle(rsp_dma_handle, NULL, 3099 rsp, real_size, DDI_DMA_READ | DDI_DMA_CONSISTENT, 3100 DDI_DMA_DONTWAIT, NULL, &rcookie, &ccount) != DDI_DMA_MAPPED) { 3101 SF_DEBUG(1, (sf, CE_WARN, 3102 "Could not bind DMA memory for ELS rsp\n")); 3103 goto fail; 3104 } 3105 rsp_bound = TRUE; 3106 3107 if (ccount != 1) { 3108 SF_DEBUG(1, (sf, CE_WARN, 3109 "Wrong cookie count for ELS rsp\n")); 3110 goto fail; 3111 } 3112 3113 privp->cmd = cmd; 3114 privp->sf = sf; 3115 privp->cmd_dma_handle = cmd_dma_handle; 3116 privp->cmd_acc_handle = cmd_acc_handle; 3117 privp->rsp = rsp; 3118 privp->rsp_dma_handle = rsp_dma_handle; 3119 privp->rsp_acc_handle = rsp_acc_handle; 3120 privp->dest_nport_id = dest_id; 3121 privp->fpkt = fpkt; 3122 3123 fpkt->fcal_pkt_cookie = sf->sf_socp; 3124 fpkt->fcal_pkt_comp = sf_els_callback; 3125 fpkt->fcal_magic = FCALP_MAGIC; 3126 fpkt->fcal_pkt_flags = 0; 3127 fpkt->fcal_socal_request.sr_soc_hdr.sh_flags = 3128 (ushort_t)(SOC_FC_HEADER | sf->sf_sochandle->fcal_portno); 3129 fpkt->fcal_socal_request.sr_soc_hdr.sh_class = 3; 3130 fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 2; 3131 fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = cmd_size; 3132 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_count = 1; 3133 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_flags = 0; 3134 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_seqno = 0; 3135 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_SIMPLE; 3136 fpkt->fcal_socal_request.sr_dataseg[0].fc_base = (uint32_t) 3137 pcookie.dmac_address; 3138 fpkt->fcal_socal_request.sr_dataseg[0].fc_count = cmd_size; 3139 fpkt->fcal_socal_request.sr_dataseg[1].fc_base = (uint32_t) 3140 rcookie.dmac_address; 3141 fpkt->fcal_socal_request.sr_dataseg[1].fc_count = rsp_size; 3142 3143 /* Fill in the Fabric Channel Header */ 3144 hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr; 3145 hp->r_ctl = R_CTL_ELS_REQ; 3146 hp->d_id = dest_id; 3147 hp->s_id = sf->sf_al_pa; 3148 hp->type = TYPE_EXTENDED_LS; 3149 hp->reserved1 = 0; 3150 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3151 hp->seq_id = 0; 3152 hp->df_ctl = 0; 3153 hp->seq_cnt = 0; 3154 hp->ox_id = 0xffff; 3155 hp->rx_id = 0xffff; 3156 hp->ro = 0; 3157 3158 *rprivp = (caddr_t)privp; 3159 *cmd_buf = cmd; 3160 return (fpkt); 3161 3162 fail: 3163 if (cmd_dma_handle != NULL) { 3164 if (cmd_bound) { 3165 (void) ddi_dma_unbind_handle(cmd_dma_handle); 3166 } 3167 ddi_dma_free_handle(&cmd_dma_handle); 3168 privp->cmd_dma_handle = NULL; 3169 } 3170 if (rsp_dma_handle != NULL) { 3171 if (rsp_bound) { 3172 (void) ddi_dma_unbind_handle(rsp_dma_handle); 3173 } 3174 ddi_dma_free_handle(&rsp_dma_handle); 3175 privp->rsp_dma_handle = NULL; 3176 } 3177 sf_els_free(fpkt); 3178 return (NULL); 3179 } 3180 3181 3182 static void 3183 sf_els_free(struct fcal_packet *fpkt) 3184 { 3185 struct sf_els_hdr *privp = fpkt->fcal_pkt_private; 3186 3187 if (privp != NULL) { 3188 if (privp->cmd_dma_handle != NULL) { 3189 (void) ddi_dma_unbind_handle(privp->cmd_dma_handle); 3190 ddi_dma_free_handle(&privp->cmd_dma_handle); 3191 } 3192 if (privp->cmd != NULL) { 3193 ddi_dma_mem_free(&privp->cmd_acc_handle); 3194 } 3195 3196 if (privp->rsp_dma_handle != NULL) { 3197 (void) ddi_dma_unbind_handle(privp->rsp_dma_handle); 3198 ddi_dma_free_handle(&privp->rsp_dma_handle); 3199 } 3200 3201 if (privp->rsp != NULL) { 3202 ddi_dma_mem_free(&privp->rsp_acc_handle); 3203 } 3204 if (privp->data_dma_handle) { 3205 (void) ddi_dma_unbind_handle(privp->data_dma_handle); 3206 ddi_dma_free_handle(&privp->data_dma_handle); 3207 } 3208 if (privp->data_buf) { 3209 ddi_dma_mem_free(&privp->data_acc_handle); 3210 } 3211 kmem_free(privp, privp->size); 3212 } 3213 kmem_free(fpkt, sizeof (struct fcal_packet)); 3214 } 3215 3216 3217 static struct sf_target * 3218 sf_create_target(struct sf *sf, struct sf_els_hdr *privp, int tnum, int64_t lun) 3219 { 3220 struct sf_target *target, *ntarget, *otarget, *ptarget; 3221 int hash; 3222 #ifdef RAID_LUNS 3223 int64_t orig_lun = lun; 3224 3225 /* XXXX Work around SCSA limitations. */ 3226 lun = *((short *)&lun); 3227 #endif 3228 ntarget = kmem_zalloc(sizeof (struct sf_target), KM_NOSLEEP); 3229 mutex_enter(&sf->sf_mutex); 3230 if (sf->sf_lip_cnt != privp->lip_cnt) { 3231 mutex_exit(&sf->sf_mutex); 3232 if (ntarget != NULL) 3233 kmem_free(ntarget, sizeof (struct sf_target)); 3234 return (NULL); 3235 } 3236 3237 target = sf_lookup_target(sf, privp->port_wwn, lun); 3238 if (lun != 0) { 3239 /* 3240 * Since LUNs != 0 are queued up after LUN == 0, find LUN == 0 3241 * and enqueue the new LUN. 3242 */ 3243 if ((ptarget = sf_lookup_target(sf, privp->port_wwn, 3244 (int64_t)0)) == NULL) { 3245 /* 3246 * Yeep -- no LUN 0? 3247 */ 3248 mutex_exit(&sf->sf_mutex); 3249 sf_log(sf, CE_WARN, "target 0x%x " 3250 "lun %" PRIx64 ": No LUN 0\n", tnum, lun); 3251 if (ntarget != NULL) 3252 kmem_free(ntarget, sizeof (struct sf_target)); 3253 return (NULL); 3254 } 3255 mutex_enter(&ptarget->sft_mutex); 3256 if (target != NULL && ptarget->sft_lip_cnt == sf->sf_lip_cnt && 3257 ptarget->sft_state&SF_TARGET_OFFLINE) { 3258 /* LUN 0 already finished, duplicate its state */ 3259 mutex_exit(&ptarget->sft_mutex); 3260 sf_offline_target(sf, target); 3261 mutex_exit(&sf->sf_mutex); 3262 if (ntarget != NULL) 3263 kmem_free(ntarget, sizeof (struct sf_target)); 3264 return (target); 3265 } else if (target != NULL) { 3266 /* 3267 * LUN 0 online or not examined yet. 3268 * Try to bring the LUN back online 3269 */ 3270 mutex_exit(&ptarget->sft_mutex); 3271 mutex_enter(&target->sft_mutex); 3272 target->sft_lip_cnt = privp->lip_cnt; 3273 target->sft_state |= SF_TARGET_BUSY; 3274 target->sft_state &= ~(SF_TARGET_OFFLINE| 3275 SF_TARGET_MARK); 3276 target->sft_al_pa = (uchar_t)privp->dest_nport_id; 3277 target->sft_hard_address = sf_switch_to_alpa[tnum]; 3278 mutex_exit(&target->sft_mutex); 3279 mutex_exit(&sf->sf_mutex); 3280 if (ntarget != NULL) 3281 kmem_free(ntarget, sizeof (struct sf_target)); 3282 return (target); 3283 } 3284 mutex_exit(&ptarget->sft_mutex); 3285 if (ntarget == NULL) { 3286 mutex_exit(&sf->sf_mutex); 3287 return (NULL); 3288 } 3289 /* Initialize new target structure */ 3290 bcopy((caddr_t)&privp->node_wwn, 3291 (caddr_t)&ntarget->sft_node_wwn, sizeof (privp->node_wwn)); 3292 bcopy((caddr_t)&privp->port_wwn, 3293 (caddr_t)&ntarget->sft_port_wwn, sizeof (privp->port_wwn)); 3294 ntarget->sft_lun.l = lun; 3295 #ifdef RAID_LUNS 3296 ntarget->sft_lun.l = orig_lun; 3297 ntarget->sft_raid_lun = (uint_t)lun; 3298 #endif 3299 mutex_init(&ntarget->sft_mutex, NULL, MUTEX_DRIVER, NULL); 3300 mutex_init(&ntarget->sft_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 3301 /* Don't let anyone use this till we finishup init. */ 3302 mutex_enter(&ntarget->sft_mutex); 3303 mutex_enter(&ntarget->sft_pkt_mutex); 3304 3305 hash = SF_HASH(privp->port_wwn, lun); 3306 ntarget->sft_next = sf->sf_wwn_lists[hash]; 3307 sf->sf_wwn_lists[hash] = ntarget; 3308 3309 ntarget->sft_lip_cnt = privp->lip_cnt; 3310 ntarget->sft_al_pa = (uchar_t)privp->dest_nport_id; 3311 ntarget->sft_hard_address = sf_switch_to_alpa[tnum]; 3312 ntarget->sft_device_type = DTYPE_UNKNOWN; 3313 ntarget->sft_state = SF_TARGET_BUSY; 3314 ntarget->sft_pkt_head = (struct sf_pkt *)&ntarget-> 3315 sft_pkt_head; 3316 ntarget->sft_pkt_tail = (struct sf_pkt *)&ntarget-> 3317 sft_pkt_head; 3318 3319 mutex_enter(&ptarget->sft_mutex); 3320 /* Traverse the list looking for this target */ 3321 for (target = ptarget; target->sft_next_lun; 3322 target = target->sft_next_lun) { 3323 otarget = target->sft_next_lun; 3324 } 3325 ntarget->sft_next_lun = target->sft_next_lun; 3326 target->sft_next_lun = ntarget; 3327 mutex_exit(&ptarget->sft_mutex); 3328 mutex_exit(&ntarget->sft_pkt_mutex); 3329 mutex_exit(&ntarget->sft_mutex); 3330 mutex_exit(&sf->sf_mutex); 3331 return (ntarget); 3332 3333 } 3334 if (target != NULL && target->sft_lip_cnt == sf->sf_lip_cnt) { 3335 /* It's been touched this LIP -- duplicate WWNs */ 3336 sf_offline_target(sf, target); /* And all the baby targets */ 3337 mutex_exit(&sf->sf_mutex); 3338 sf_log(sf, CE_WARN, "target 0x%x, duplicate port wwns\n", 3339 tnum); 3340 if (ntarget != NULL) { 3341 kmem_free(ntarget, sizeof (struct sf_target)); 3342 } 3343 return (NULL); 3344 } 3345 3346 if ((otarget = sf->sf_targets[tnum]) != NULL) { 3347 /* Someone else is in our slot */ 3348 mutex_enter(&otarget->sft_mutex); 3349 if (otarget->sft_lip_cnt == sf->sf_lip_cnt) { 3350 mutex_exit(&otarget->sft_mutex); 3351 sf_offline_target(sf, otarget); 3352 if (target != NULL) 3353 sf_offline_target(sf, target); 3354 mutex_exit(&sf->sf_mutex); 3355 sf_log(sf, CE_WARN, 3356 "target 0x%x, duplicate switch settings\n", tnum); 3357 if (ntarget != NULL) 3358 kmem_free(ntarget, sizeof (struct sf_target)); 3359 return (NULL); 3360 } 3361 mutex_exit(&otarget->sft_mutex); 3362 if (bcmp((caddr_t)&privp->port_wwn, (caddr_t)&otarget-> 3363 sft_port_wwn, sizeof (privp->port_wwn))) { 3364 sf_offline_target(sf, otarget); 3365 mutex_exit(&sf->sf_mutex); 3366 sf_log(sf, CE_WARN, "wwn changed on target 0x%x\n", 3367 tnum); 3368 bzero((caddr_t)&sf->sf_stats.tstats[tnum], 3369 sizeof (struct sf_target_stats)); 3370 mutex_enter(&sf->sf_mutex); 3371 } 3372 } 3373 3374 sf->sf_targets[tnum] = target; 3375 if ((target = sf->sf_targets[tnum]) == NULL) { 3376 if (ntarget == NULL) { 3377 mutex_exit(&sf->sf_mutex); 3378 return (NULL); 3379 } 3380 bcopy((caddr_t)&privp->node_wwn, 3381 (caddr_t)&ntarget->sft_node_wwn, sizeof (privp->node_wwn)); 3382 bcopy((caddr_t)&privp->port_wwn, 3383 (caddr_t)&ntarget->sft_port_wwn, sizeof (privp->port_wwn)); 3384 ntarget->sft_lun.l = lun; 3385 #ifdef RAID_LUNS 3386 ntarget->sft_lun.l = orig_lun; 3387 ntarget->sft_raid_lun = (uint_t)lun; 3388 #endif 3389 mutex_init(&ntarget->sft_mutex, NULL, MUTEX_DRIVER, NULL); 3390 mutex_init(&ntarget->sft_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 3391 mutex_enter(&ntarget->sft_mutex); 3392 mutex_enter(&ntarget->sft_pkt_mutex); 3393 hash = SF_HASH(privp->port_wwn, lun); /* lun 0 */ 3394 ntarget->sft_next = sf->sf_wwn_lists[hash]; 3395 sf->sf_wwn_lists[hash] = ntarget; 3396 3397 target = ntarget; 3398 target->sft_lip_cnt = privp->lip_cnt; 3399 target->sft_al_pa = (uchar_t)privp->dest_nport_id; 3400 target->sft_hard_address = sf_switch_to_alpa[tnum]; 3401 target->sft_device_type = DTYPE_UNKNOWN; 3402 target->sft_state = SF_TARGET_BUSY; 3403 target->sft_pkt_head = (struct sf_pkt *)&target-> 3404 sft_pkt_head; 3405 target->sft_pkt_tail = (struct sf_pkt *)&target-> 3406 sft_pkt_head; 3407 sf->sf_targets[tnum] = target; 3408 mutex_exit(&ntarget->sft_mutex); 3409 mutex_exit(&ntarget->sft_pkt_mutex); 3410 mutex_exit(&sf->sf_mutex); 3411 } else { 3412 mutex_enter(&target->sft_mutex); 3413 target->sft_lip_cnt = privp->lip_cnt; 3414 target->sft_state |= SF_TARGET_BUSY; 3415 target->sft_state &= ~(SF_TARGET_OFFLINE|SF_TARGET_MARK); 3416 target->sft_al_pa = (uchar_t)privp->dest_nport_id; 3417 target->sft_hard_address = sf_switch_to_alpa[tnum]; 3418 mutex_exit(&target->sft_mutex); 3419 mutex_exit(&sf->sf_mutex); 3420 if (ntarget != NULL) 3421 kmem_free(ntarget, sizeof (struct sf_target)); 3422 } 3423 return (target); 3424 } 3425 3426 3427 /* 3428 * find the target for a given sf instance 3429 */ 3430 /* ARGSUSED */ 3431 static struct sf_target * 3432 #ifdef RAID_LUNS 3433 sf_lookup_target(struct sf *sf, uchar_t *wwn, int lun) 3434 #else 3435 sf_lookup_target(struct sf *sf, uchar_t *wwn, int64_t lun) 3436 #endif 3437 { 3438 int hash; 3439 struct sf_target *target; 3440 3441 ASSERT(mutex_owned(&sf->sf_mutex)); 3442 hash = SF_HASH(wwn, lun); 3443 3444 target = sf->sf_wwn_lists[hash]; 3445 while (target != NULL) { 3446 3447 #ifndef RAID_LUNS 3448 if (bcmp((caddr_t)wwn, (caddr_t)&target->sft_port_wwn, 3449 sizeof (target->sft_port_wwn)) == 0 && 3450 target->sft_lun.l == lun) 3451 break; 3452 #else 3453 if (bcmp((caddr_t)wwn, (caddr_t)&target->sft_port_wwn, 3454 sizeof (target->sft_port_wwn)) == 0 && 3455 target->sft_raid_lun == lun) 3456 break; 3457 #endif 3458 target = target->sft_next; 3459 } 3460 3461 return (target); 3462 } 3463 3464 3465 /* 3466 * Send out a REPORT_LUNS command. 3467 */ 3468 static int 3469 sf_do_reportlun(struct sf *sf, struct sf_els_hdr *privp, 3470 struct sf_target *target) 3471 { 3472 struct fcal_packet *fpkt = privp->fpkt; 3473 ddi_dma_cookie_t pcookie; 3474 ddi_dma_handle_t lun_dma_handle = NULL; 3475 ddi_acc_handle_t lun_acc_handle; 3476 uint_t ccount; 3477 size_t real_size; 3478 caddr_t lun_buf = NULL; 3479 int handle_bound = 0; 3480 fc_frame_header_t *hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr; 3481 struct fcp_cmd *reportlun = (struct fcp_cmd *)privp->cmd; 3482 char *msg = "Transport"; 3483 3484 if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr, 3485 DDI_DMA_DONTWAIT, NULL, &lun_dma_handle) != DDI_SUCCESS) { 3486 msg = "ddi_dma_alloc_handle()"; 3487 goto fail; 3488 } 3489 3490 if (ddi_dma_mem_alloc(lun_dma_handle, REPORT_LUNS_SIZE, 3491 sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT, 3492 DDI_DMA_DONTWAIT, NULL, &lun_buf, 3493 &real_size, &lun_acc_handle) != DDI_SUCCESS) { 3494 msg = "ddi_dma_mem_alloc()"; 3495 goto fail; 3496 } 3497 3498 if (real_size < REPORT_LUNS_SIZE) { 3499 msg = "DMA mem < REPORT_LUNS_SIZE"; 3500 goto fail; 3501 } 3502 3503 if (ddi_dma_addr_bind_handle(lun_dma_handle, NULL, 3504 lun_buf, real_size, DDI_DMA_READ | 3505 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 3506 NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) { 3507 msg = "ddi_dma_addr_bind_handle()"; 3508 goto fail; 3509 } 3510 handle_bound = 1; 3511 3512 if (ccount != 1) { 3513 msg = "ccount != 1"; 3514 goto fail; 3515 } 3516 privp->els_code = 0; 3517 privp->target = target; 3518 privp->data_dma_handle = lun_dma_handle; 3519 privp->data_acc_handle = lun_acc_handle; 3520 privp->data_buf = lun_buf; 3521 3522 fpkt->fcal_pkt_comp = sf_reportlun_callback; 3523 fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3; 3524 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_IO_READ; 3525 fpkt->fcal_socal_request.sr_dataseg[0].fc_count = 3526 sizeof (struct fcp_cmd); 3527 fpkt->fcal_socal_request.sr_dataseg[2].fc_base = 3528 (uint32_t)pcookie.dmac_address; 3529 fpkt->fcal_socal_request.sr_dataseg[2].fc_count = pcookie.dmac_size; 3530 fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = pcookie.dmac_size; 3531 hp->r_ctl = R_CTL_COMMAND; 3532 hp->type = TYPE_SCSI_FCP; 3533 bzero((caddr_t)reportlun, sizeof (struct fcp_cmd)); 3534 ((union scsi_cdb *)reportlun->fcp_cdb)->scc_cmd = SCMD_REPORT_LUNS; 3535 /* Now set the buffer size. If DDI gave us extra, that's O.K. */ 3536 ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count0 = 3537 (real_size&0x0ff); 3538 ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count1 = 3539 (real_size>>8)&0x0ff; 3540 ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count2 = 3541 (real_size>>16)&0x0ff; 3542 ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count3 = 3543 (real_size>>24)&0x0ff; 3544 reportlun->fcp_cntl.cntl_read_data = 1; 3545 reportlun->fcp_cntl.cntl_write_data = 0; 3546 reportlun->fcp_data_len = pcookie.dmac_size; 3547 reportlun->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 3548 3549 (void) ddi_dma_sync(lun_dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); 3550 /* We know he's there, so this should be fast */ 3551 privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT; 3552 if (sf_els_transport(sf, privp) == 1) 3553 return (1); 3554 3555 fail: 3556 sf_log(sf, CE_WARN, 3557 "%s failure for REPORTLUN to target 0x%x\n", 3558 msg, sf_alpa_to_switch[privp->dest_nport_id]); 3559 sf_els_free(fpkt); 3560 if (lun_dma_handle != NULL) { 3561 if (handle_bound) 3562 (void) ddi_dma_unbind_handle(lun_dma_handle); 3563 ddi_dma_free_handle(&lun_dma_handle); 3564 } 3565 if (lun_buf != NULL) { 3566 ddi_dma_mem_free(&lun_acc_handle); 3567 } 3568 return (0); 3569 } 3570 3571 /* 3572 * Handle the results of a REPORT_LUNS command: 3573 * Create additional targets if necessary 3574 * Initiate INQUIRYs on all LUNs. 3575 */ 3576 static void 3577 sf_reportlun_callback(struct fcal_packet *fpkt) 3578 { 3579 struct sf_els_hdr *privp = (struct sf_els_hdr *)fpkt-> 3580 fcal_pkt_private; 3581 struct scsi_report_luns *ptr = 3582 (struct scsi_report_luns *)privp->data_buf; 3583 struct sf *sf = privp->sf; 3584 struct sf_target *target = privp->target; 3585 struct fcp_rsp *rsp = NULL; 3586 int delayed_retry = 0; 3587 int tid = sf_alpa_to_switch[target->sft_hard_address]; 3588 int i, free_pkt = 1; 3589 short ncmds; 3590 3591 mutex_enter(&sf->sf_mutex); 3592 /* use as temporary state variable */ 3593 if (privp->timeout == SF_INVALID_TIMEOUT) { 3594 mutex_exit(&sf->sf_mutex); 3595 return; 3596 } 3597 if (privp->prev) 3598 privp->prev->next = privp->next; 3599 if (privp->next) 3600 privp->next->prev = privp->prev; 3601 if (sf->sf_els_list == privp) 3602 sf->sf_els_list = privp->next; 3603 privp->prev = privp->next = NULL; 3604 mutex_exit(&sf->sf_mutex); 3605 ncmds = fpkt->fcal_ncmds; 3606 ASSERT(ncmds >= 0); 3607 mutex_enter(&sf->sf_cmd_mutex); 3608 sf->sf_ncmds = ncmds; 3609 mutex_exit(&sf->sf_cmd_mutex); 3610 3611 if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) { 3612 (void) ddi_dma_sync(privp->rsp_dma_handle, 0, 3613 0, DDI_DMA_SYNC_FORKERNEL); 3614 3615 rsp = (struct fcp_rsp *)privp->rsp; 3616 } 3617 SF_DEBUG(1, (sf, CE_CONT, 3618 "!REPORTLUN to al_pa %x pkt status %x scsi status %x\n", 3619 privp->dest_nport_id, 3620 fpkt->fcal_pkt_status, 3621 rsp?rsp->fcp_u.fcp_status.scsi_status:0)); 3622 3623 /* See if target simply does not support REPORT_LUNS. */ 3624 if (rsp && rsp->fcp_u.fcp_status.scsi_status == STATUS_CHECK && 3625 rsp->fcp_u.fcp_status.sense_len_set && 3626 rsp->fcp_sense_len >= 3627 offsetof(struct scsi_extended_sense, es_qual_code)) { 3628 struct scsi_extended_sense *sense; 3629 sense = (struct scsi_extended_sense *) 3630 ((caddr_t)rsp + sizeof (struct fcp_rsp) 3631 + rsp->fcp_response_len); 3632 if (sense->es_key == KEY_ILLEGAL_REQUEST) { 3633 if (sense->es_add_code == 0x20) { 3634 /* Fake LUN 0 */ 3635 SF_DEBUG(1, (sf, CE_CONT, 3636 "!REPORTLUN Faking good " 3637 "completion for alpa %x\n", 3638 privp->dest_nport_id)); 3639 ptr->lun_list_len = FCP_LUN_SIZE; 3640 ptr->lun[0] = 0; 3641 rsp->fcp_u.fcp_status.scsi_status = 3642 STATUS_GOOD; 3643 } else if (sense->es_add_code == 0x25) { 3644 SF_DEBUG(1, (sf, CE_CONT, 3645 "!REPORTLUN device alpa %x " 3646 "key %x code %x\n", 3647 privp->dest_nport_id, 3648 sense->es_key, sense->es_add_code)); 3649 goto fail; 3650 } 3651 } else if (sense->es_key == 3652 KEY_UNIT_ATTENTION && 3653 sense->es_add_code == 0x29) { 3654 SF_DEBUG(1, (sf, CE_CONT, 3655 "!REPORTLUN device alpa %x was reset\n", 3656 privp->dest_nport_id)); 3657 } else { 3658 SF_DEBUG(1, (sf, CE_CONT, 3659 "!REPORTLUN device alpa %x " 3660 "key %x code %x\n", 3661 privp->dest_nport_id, 3662 sense->es_key, sense->es_add_code)); 3663 /* XXXXXX The following is here to handle broken targets -- remove it later */ 3664 if (sf_reportlun_forever && 3665 sense->es_key == KEY_UNIT_ATTENTION) 3666 goto retry; 3667 /* XXXXXX */ 3668 if (sense->es_key == KEY_NOT_READY) 3669 delayed_retry = 1; 3670 } 3671 } 3672 3673 if (rsp && rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD) { 3674 struct fcp_rsp_info *bep; 3675 3676 bep = (struct fcp_rsp_info *)(&rsp-> 3677 fcp_response_len + 1); 3678 if (!rsp->fcp_u.fcp_status.rsp_len_set || 3679 bep->rsp_code == FCP_NO_FAILURE) { 3680 (void) ddi_dma_sync(privp->data_dma_handle, 3681 0, 0, DDI_DMA_SYNC_FORKERNEL); 3682 3683 /* Convert from #bytes to #ints */ 3684 ptr->lun_list_len = ptr->lun_list_len >> 3; 3685 SF_DEBUG(2, (sf, CE_CONT, 3686 "!REPORTLUN to al_pa %x succeeded: %d LUNs\n", 3687 privp->dest_nport_id, ptr->lun_list_len)); 3688 if (!ptr->lun_list_len) { 3689 /* No LUNs? Ya gotta be kidding... */ 3690 sf_log(sf, CE_WARN, 3691 "SCSI violation -- " 3692 "target 0x%x reports no LUNs\n", 3693 sf_alpa_to_switch[ 3694 privp->dest_nport_id]); 3695 ptr->lun_list_len = 1; 3696 ptr->lun[0] = 0; 3697 } 3698 3699 mutex_enter(&sf->sf_mutex); 3700 if (sf->sf_lip_cnt == privp->lip_cnt) { 3701 sf->sf_device_count += ptr->lun_list_len - 1; 3702 } 3703 3704 mutex_exit(&sf->sf_mutex); 3705 for (i = 0; i < ptr->lun_list_len && privp->lip_cnt == 3706 sf->sf_lip_cnt; i++) { 3707 struct sf_els_hdr *nprivp; 3708 struct fcal_packet *nfpkt; 3709 3710 /* LUN 0 is already in `target' */ 3711 if (ptr->lun[i] != 0) { 3712 target = sf_create_target(sf, 3713 privp, tid, ptr->lun[i]); 3714 } 3715 nprivp = NULL; 3716 nfpkt = NULL; 3717 if (target) { 3718 nfpkt = sf_els_alloc(sf, 3719 target->sft_al_pa, 3720 sizeof (struct sf_els_hdr), 3721 sizeof (union sf_els_cmd), 3722 sizeof (union sf_els_rsp), 3723 (caddr_t *)&nprivp, 3724 (caddr_t *)&rsp); 3725 if (nprivp) 3726 nprivp->lip_cnt = 3727 privp->lip_cnt; 3728 } 3729 if (nfpkt && nprivp && 3730 (sf_do_inquiry(sf, nprivp, target) == 3731 0)) { 3732 mutex_enter(&sf->sf_mutex); 3733 if (sf->sf_lip_cnt == privp-> 3734 lip_cnt) { 3735 sf->sf_device_count --; 3736 } 3737 sf_offline_target(sf, target); 3738 mutex_exit(&sf->sf_mutex); 3739 } 3740 } 3741 sf_els_free(fpkt); 3742 return; 3743 } else { 3744 SF_DEBUG(1, (sf, CE_CONT, 3745 "!REPORTLUN al_pa %x fcp failure, " 3746 "fcp_rsp_code %x scsi status %x\n", 3747 privp->dest_nport_id, bep->rsp_code, 3748 rsp ? rsp->fcp_u.fcp_status.scsi_status:0)); 3749 goto fail; 3750 } 3751 } 3752 if (rsp && ((rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) || 3753 (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL))) { 3754 delayed_retry = 1; 3755 } 3756 3757 if (++(privp->retries) < sf_els_retries || 3758 (delayed_retry && privp->retries < SF_BSY_RETRIES)) { 3759 /* XXXXXX The following is here to handle broken targets -- remove it later */ 3760 retry: 3761 /* XXXXXX */ 3762 if (delayed_retry) { 3763 privp->retries--; 3764 privp->timeout = sf_watchdog_time + SF_BSY_TIMEOUT; 3765 privp->delayed_retry = 1; 3766 } else { 3767 privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT; 3768 } 3769 3770 privp->prev = NULL; 3771 mutex_enter(&sf->sf_mutex); 3772 if (privp->lip_cnt == sf->sf_lip_cnt) { 3773 if (!delayed_retry) 3774 SF_DEBUG(1, (sf, CE_WARN, 3775 "!REPORTLUN to al_pa %x failed, retrying\n", 3776 privp->dest_nport_id)); 3777 privp->next = sf->sf_els_list; 3778 if (sf->sf_els_list != NULL) 3779 sf->sf_els_list->prev = privp; 3780 sf->sf_els_list = privp; 3781 mutex_exit(&sf->sf_mutex); 3782 if (!delayed_retry && soc_transport(sf->sf_sochandle, 3783 fpkt, FCAL_NOSLEEP, CQ_REQUEST_1) != 3784 FCAL_TRANSPORT_SUCCESS) { 3785 mutex_enter(&sf->sf_mutex); 3786 if (privp->prev) 3787 privp->prev->next = privp->next; 3788 if (privp->next) 3789 privp->next->prev = privp->prev; 3790 if (sf->sf_els_list == privp) 3791 sf->sf_els_list = privp->next; 3792 mutex_exit(&sf->sf_mutex); 3793 goto fail; 3794 } else 3795 return; 3796 } else { 3797 mutex_exit(&sf->sf_mutex); 3798 } 3799 } else { 3800 fail: 3801 3802 /* REPORT_LUN failed -- try inquiry */ 3803 if (sf_do_inquiry(sf, privp, target) != 0) { 3804 return; 3805 } else { 3806 free_pkt = 0; 3807 } 3808 mutex_enter(&sf->sf_mutex); 3809 if (sf->sf_lip_cnt == privp->lip_cnt) { 3810 sf_log(sf, CE_WARN, 3811 "!REPORTLUN to target 0x%x failed\n", 3812 sf_alpa_to_switch[privp->dest_nport_id]); 3813 sf_offline_target(sf, target); 3814 sf->sf_device_count--; 3815 ASSERT(sf->sf_device_count >= 0); 3816 if (sf->sf_device_count == 0) 3817 sf_finish_init(sf, privp->lip_cnt); 3818 } 3819 mutex_exit(&sf->sf_mutex); 3820 } 3821 if (free_pkt) { 3822 sf_els_free(fpkt); 3823 } 3824 } 3825 3826 static int 3827 sf_do_inquiry(struct sf *sf, struct sf_els_hdr *privp, 3828 struct sf_target *target) 3829 { 3830 struct fcal_packet *fpkt = privp->fpkt; 3831 ddi_dma_cookie_t pcookie; 3832 ddi_dma_handle_t inq_dma_handle = NULL; 3833 ddi_acc_handle_t inq_acc_handle; 3834 uint_t ccount; 3835 size_t real_size; 3836 caddr_t inq_buf = NULL; 3837 int handle_bound = FALSE; 3838 fc_frame_header_t *hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr; 3839 struct fcp_cmd *inq = (struct fcp_cmd *)privp->cmd; 3840 char *msg = "Transport"; 3841 3842 3843 if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr, 3844 DDI_DMA_DONTWAIT, NULL, &inq_dma_handle) != DDI_SUCCESS) { 3845 msg = "ddi_dma_alloc_handle()"; 3846 goto fail; 3847 } 3848 3849 if (ddi_dma_mem_alloc(inq_dma_handle, SUN_INQSIZE, 3850 sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT, 3851 DDI_DMA_DONTWAIT, NULL, &inq_buf, 3852 &real_size, &inq_acc_handle) != DDI_SUCCESS) { 3853 msg = "ddi_dma_mem_alloc()"; 3854 goto fail; 3855 } 3856 3857 if (real_size < SUN_INQSIZE) { 3858 msg = "DMA mem < inquiry size"; 3859 goto fail; 3860 } 3861 3862 if (ddi_dma_addr_bind_handle(inq_dma_handle, NULL, 3863 inq_buf, real_size, DDI_DMA_READ | DDI_DMA_CONSISTENT, 3864 DDI_DMA_DONTWAIT, NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) { 3865 msg = "ddi_dma_addr_bind_handle()"; 3866 goto fail; 3867 } 3868 handle_bound = TRUE; 3869 3870 if (ccount != 1) { 3871 msg = "ccount != 1"; 3872 goto fail; 3873 } 3874 privp->els_code = 0; /* not an ELS command */ 3875 privp->target = target; 3876 privp->data_dma_handle = inq_dma_handle; 3877 privp->data_acc_handle = inq_acc_handle; 3878 privp->data_buf = inq_buf; 3879 fpkt->fcal_pkt_comp = sf_inq_callback; 3880 fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3; 3881 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_IO_READ; 3882 fpkt->fcal_socal_request.sr_dataseg[0].fc_count = 3883 sizeof (struct fcp_cmd); 3884 fpkt->fcal_socal_request.sr_dataseg[2].fc_base = 3885 (uint32_t)pcookie.dmac_address; 3886 fpkt->fcal_socal_request.sr_dataseg[2].fc_count = pcookie.dmac_size; 3887 fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = pcookie.dmac_size; 3888 hp->r_ctl = R_CTL_COMMAND; 3889 hp->type = TYPE_SCSI_FCP; 3890 bzero((caddr_t)inq, sizeof (struct fcp_cmd)); 3891 ((union scsi_cdb *)inq->fcp_cdb)->scc_cmd = SCMD_INQUIRY; 3892 ((union scsi_cdb *)inq->fcp_cdb)->g0_count0 = SUN_INQSIZE; 3893 bcopy((caddr_t)&target->sft_lun.b, (caddr_t)&inq->fcp_ent_addr, 3894 FCP_LUN_SIZE); 3895 inq->fcp_cntl.cntl_read_data = 1; 3896 inq->fcp_cntl.cntl_write_data = 0; 3897 inq->fcp_data_len = pcookie.dmac_size; 3898 inq->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 3899 3900 (void) ddi_dma_sync(inq_dma_handle, (off_t)0, (size_t)0, 3901 DDI_DMA_SYNC_FORDEV); 3902 privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT; 3903 SF_DEBUG(5, (sf, CE_WARN, 3904 "!Sending INQUIRY to al_pa %x lun %" PRIx64 "\n", 3905 privp->dest_nport_id, 3906 SCSA_LUN(target))); 3907 return (sf_els_transport(sf, privp)); 3908 3909 fail: 3910 sf_log(sf, CE_WARN, 3911 "%s failure for INQUIRY to target 0x%x\n", 3912 msg, sf_alpa_to_switch[privp->dest_nport_id]); 3913 sf_els_free(fpkt); 3914 if (inq_dma_handle != NULL) { 3915 if (handle_bound) { 3916 (void) ddi_dma_unbind_handle(inq_dma_handle); 3917 } 3918 ddi_dma_free_handle(&inq_dma_handle); 3919 } 3920 if (inq_buf != NULL) { 3921 ddi_dma_mem_free(&inq_acc_handle); 3922 } 3923 return (FALSE); 3924 } 3925 3926 3927 /* 3928 * called as the pkt_comp routine for INQ packets 3929 */ 3930 static void 3931 sf_inq_callback(struct fcal_packet *fpkt) 3932 { 3933 struct sf_els_hdr *privp = (struct sf_els_hdr *)fpkt-> 3934 fcal_pkt_private; 3935 struct scsi_inquiry *prt = (struct scsi_inquiry *)privp->data_buf; 3936 struct sf *sf = privp->sf; 3937 struct sf *tsf; 3938 struct sf_target *target = privp->target; 3939 struct fcp_rsp *rsp; 3940 int delayed_retry = FALSE; 3941 short ncmds; 3942 3943 3944 mutex_enter(&sf->sf_mutex); 3945 /* use as temporary state variable */ 3946 if (privp->timeout == SF_INVALID_TIMEOUT) { 3947 mutex_exit(&sf->sf_mutex); 3948 return; 3949 } 3950 if (privp->prev != NULL) { 3951 privp->prev->next = privp->next; 3952 } 3953 if (privp->next != NULL) { 3954 privp->next->prev = privp->prev; 3955 } 3956 if (sf->sf_els_list == privp) { 3957 sf->sf_els_list = privp->next; 3958 } 3959 privp->prev = privp->next = NULL; 3960 mutex_exit(&sf->sf_mutex); 3961 ncmds = fpkt->fcal_ncmds; 3962 ASSERT(ncmds >= 0); 3963 mutex_enter(&sf->sf_cmd_mutex); 3964 sf->sf_ncmds = ncmds; 3965 mutex_exit(&sf->sf_cmd_mutex); 3966 3967 if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) { 3968 3969 (void) ddi_dma_sync(privp->rsp_dma_handle, (off_t)0, 3970 (size_t)0, DDI_DMA_SYNC_FORKERNEL); 3971 3972 rsp = (struct fcp_rsp *)privp->rsp; 3973 SF_DEBUG(2, (sf, CE_CONT, 3974 "!INQUIRY to al_pa %x scsi status %x", 3975 privp->dest_nport_id, rsp->fcp_u.fcp_status.scsi_status)); 3976 3977 if ((rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD) && 3978 !rsp->fcp_u.fcp_status.resid_over && 3979 (!rsp->fcp_u.fcp_status.resid_under || 3980 ((SUN_INQSIZE - rsp->fcp_resid) >= SUN_MIN_INQLEN))) { 3981 struct fcp_rsp_info *bep; 3982 3983 bep = (struct fcp_rsp_info *)(&rsp-> 3984 fcp_response_len + 1); 3985 3986 if (!rsp->fcp_u.fcp_status.rsp_len_set || 3987 (bep->rsp_code == FCP_NO_FAILURE)) { 3988 3989 SF_DEBUG(2, (sf, CE_CONT, 3990 "!INQUIRY to al_pa %x lun %" PRIx64 3991 " succeeded\n", 3992 privp->dest_nport_id, SCSA_LUN(target))); 3993 3994 (void) ddi_dma_sync(privp->data_dma_handle, 3995 (off_t)0, (size_t)0, 3996 DDI_DMA_SYNC_FORKERNEL); 3997 3998 mutex_enter(&sf->sf_mutex); 3999 4000 if (sf->sf_lip_cnt == privp->lip_cnt) { 4001 mutex_enter(&target->sft_mutex); 4002 target->sft_device_type = 4003 prt->inq_dtype; 4004 bcopy(prt, &target->sft_inq, 4005 sizeof (*prt)); 4006 mutex_exit(&target->sft_mutex); 4007 sf->sf_device_count--; 4008 ASSERT(sf->sf_device_count >= 0); 4009 if (sf->sf_device_count == 0) { 4010 sf_finish_init(sf, 4011 privp->lip_cnt); 4012 } 4013 } 4014 mutex_exit(&sf->sf_mutex); 4015 sf_els_free(fpkt); 4016 return; 4017 } 4018 } else if ((rsp->fcp_u.fcp_status.scsi_status == 4019 STATUS_BUSY) || 4020 (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL) || 4021 (rsp->fcp_u.fcp_status.scsi_status == STATUS_CHECK)) { 4022 delayed_retry = TRUE; 4023 } 4024 } else { 4025 SF_DEBUG(2, (sf, CE_CONT, "!INQUIRY to al_pa %x fc status %x", 4026 privp->dest_nport_id, fpkt->fcal_pkt_status)); 4027 } 4028 4029 if (++(privp->retries) < sf_els_retries || 4030 (delayed_retry && privp->retries < SF_BSY_RETRIES)) { 4031 if (fpkt->fcal_pkt_status == FCAL_STATUS_MAX_XCHG_EXCEEDED) { 4032 tsf = sf->sf_sibling; 4033 if (tsf != NULL) { 4034 mutex_enter(&tsf->sf_cmd_mutex); 4035 tsf->sf_flag = 1; 4036 tsf->sf_throttle = SF_DECR_DELTA; 4037 mutex_exit(&tsf->sf_cmd_mutex); 4038 } 4039 delayed_retry = 1; 4040 } 4041 if (delayed_retry) { 4042 privp->retries--; 4043 privp->timeout = sf_watchdog_time + SF_BSY_TIMEOUT; 4044 privp->delayed_retry = TRUE; 4045 } else { 4046 privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT; 4047 } 4048 4049 privp->prev = NULL; 4050 mutex_enter(&sf->sf_mutex); 4051 if (privp->lip_cnt == sf->sf_lip_cnt) { 4052 if (!delayed_retry) { 4053 SF_DEBUG(1, (sf, CE_WARN, 4054 "INQUIRY to al_pa %x failed, retrying", 4055 privp->dest_nport_id)); 4056 } 4057 privp->next = sf->sf_els_list; 4058 if (sf->sf_els_list != NULL) { 4059 sf->sf_els_list->prev = privp; 4060 } 4061 sf->sf_els_list = privp; 4062 mutex_exit(&sf->sf_mutex); 4063 /* if not delayed call transport to send a pkt */ 4064 if (!delayed_retry && 4065 (soc_transport(sf->sf_sochandle, fpkt, 4066 FCAL_NOSLEEP, CQ_REQUEST_1) != 4067 FCAL_TRANSPORT_SUCCESS)) { 4068 mutex_enter(&sf->sf_mutex); 4069 if (privp->prev != NULL) { 4070 privp->prev->next = privp->next; 4071 } 4072 if (privp->next != NULL) { 4073 privp->next->prev = privp->prev; 4074 } 4075 if (sf->sf_els_list == privp) { 4076 sf->sf_els_list = privp->next; 4077 } 4078 mutex_exit(&sf->sf_mutex); 4079 goto fail; 4080 } 4081 return; 4082 } 4083 mutex_exit(&sf->sf_mutex); 4084 } else { 4085 fail: 4086 mutex_enter(&sf->sf_mutex); 4087 if (sf->sf_lip_cnt == privp->lip_cnt) { 4088 sf_offline_target(sf, target); 4089 sf_log(sf, CE_NOTE, 4090 "INQUIRY to target 0x%x lun %" PRIx64 " failed. " 4091 "Retry Count: %d\n", 4092 sf_alpa_to_switch[privp->dest_nport_id], 4093 SCSA_LUN(target), 4094 privp->retries); 4095 sf->sf_device_count--; 4096 ASSERT(sf->sf_device_count >= 0); 4097 if (sf->sf_device_count == 0) { 4098 sf_finish_init(sf, privp->lip_cnt); 4099 } 4100 } 4101 mutex_exit(&sf->sf_mutex); 4102 } 4103 sf_els_free(fpkt); 4104 } 4105 4106 4107 static void 4108 sf_finish_init(struct sf *sf, int lip_cnt) 4109 { 4110 int i; /* loop index */ 4111 int cflag; 4112 struct sf_target *target; /* current target */ 4113 dev_info_t *dip; 4114 struct sf_hp_elem *elem; /* hotplug element created */ 4115 4116 SF_DEBUG(1, (sf, CE_WARN, "!sf_finish_init\n")); 4117 ASSERT(mutex_owned(&sf->sf_mutex)); 4118 4119 /* scan all hash queues */ 4120 for (i = 0; i < SF_NUM_HASH_QUEUES; i++) { 4121 target = sf->sf_wwn_lists[i]; 4122 while (target != NULL) { 4123 mutex_enter(&target->sft_mutex); 4124 4125 /* see if target is not offline */ 4126 if ((target->sft_state & SF_TARGET_OFFLINE)) { 4127 /* 4128 * target already offline 4129 */ 4130 mutex_exit(&target->sft_mutex); 4131 goto next_entry; 4132 } 4133 4134 /* 4135 * target is not already offline -- see if it has 4136 * already been marked as ready to go offline 4137 */ 4138 if (target->sft_state & SF_TARGET_MARK) { 4139 /* 4140 * target already marked, so take it offline 4141 */ 4142 mutex_exit(&target->sft_mutex); 4143 sf_offline_target(sf, target); 4144 goto next_entry; 4145 } 4146 4147 /* clear target busy flag */ 4148 target->sft_state &= ~SF_TARGET_BUSY; 4149 4150 /* is target init not yet done ?? */ 4151 cflag = !(target->sft_state & SF_TARGET_INIT_DONE); 4152 4153 /* get pointer to target dip */ 4154 dip = target->sft_dip; 4155 4156 mutex_exit(&target->sft_mutex); 4157 mutex_exit(&sf->sf_mutex); 4158 4159 if (cflag && (dip == NULL)) { 4160 /* 4161 * target init not yet done && 4162 * devinfo not yet created 4163 */ 4164 sf_create_devinfo(sf, target, lip_cnt); 4165 mutex_enter(&sf->sf_mutex); 4166 goto next_entry; 4167 } 4168 4169 /* 4170 * target init already done || devinfo already created 4171 */ 4172 ASSERT(dip != NULL); 4173 if (!sf_create_props(dip, target, lip_cnt)) { 4174 /* a problem creating properties */ 4175 mutex_enter(&sf->sf_mutex); 4176 goto next_entry; 4177 } 4178 4179 /* create a new element for the hotplug list */ 4180 if ((elem = kmem_zalloc(sizeof (struct sf_hp_elem), 4181 KM_NOSLEEP)) != NULL) { 4182 4183 /* fill in the new element */ 4184 elem->dip = dip; 4185 elem->target = target; 4186 elem->what = SF_ONLINE; 4187 4188 /* add the new element into the hotplug list */ 4189 mutex_enter(&sf->sf_hp_daemon_mutex); 4190 if (sf->sf_hp_elem_tail != NULL) { 4191 sf->sf_hp_elem_tail->next = elem; 4192 sf->sf_hp_elem_tail = elem; 4193 } else { 4194 /* this is the first element in list */ 4195 sf->sf_hp_elem_head = 4196 sf->sf_hp_elem_tail = 4197 elem; 4198 } 4199 cv_signal(&sf->sf_hp_daemon_cv); 4200 mutex_exit(&sf->sf_hp_daemon_mutex); 4201 } else { 4202 /* could not allocate memory for element ?? */ 4203 (void) ndi_devi_online_async(dip, 0); 4204 } 4205 4206 mutex_enter(&sf->sf_mutex); 4207 4208 next_entry: 4209 /* ensure no new LIPs have occurred */ 4210 if (sf->sf_lip_cnt != lip_cnt) { 4211 return; 4212 } 4213 target = target->sft_next; 4214 } 4215 4216 /* done scanning all targets in this queue */ 4217 } 4218 4219 /* done with all hash queues */ 4220 4221 sf->sf_state = SF_STATE_ONLINE; 4222 sf->sf_online_timer = 0; 4223 } 4224 4225 4226 /* 4227 * create devinfo node 4228 */ 4229 static void 4230 sf_create_devinfo(struct sf *sf, struct sf_target *target, int lip_cnt) 4231 { 4232 dev_info_t *cdip = NULL; 4233 char *nname = NULL; 4234 char **compatible = NULL; 4235 int ncompatible; 4236 struct scsi_inquiry *inq = &target->sft_inq; 4237 char *scsi_binding_set; 4238 4239 /* get the 'scsi-binding-set' property */ 4240 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, sf->sf_dip, 4241 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 4242 &scsi_binding_set) != DDI_PROP_SUCCESS) 4243 scsi_binding_set = NULL; 4244 4245 /* determine the node name and compatible */ 4246 scsi_hba_nodename_compatible_get(inq, scsi_binding_set, 4247 inq->inq_dtype, NULL, &nname, &compatible, &ncompatible); 4248 if (scsi_binding_set) 4249 ddi_prop_free(scsi_binding_set); 4250 4251 /* if nodename can't be determined then print a message and skip it */ 4252 if (nname == NULL) { 4253 #ifndef RAID_LUNS 4254 sf_log(sf, CE_WARN, "%s%d: no driver for device " 4255 "@w%02x%02x%02x%02x%02x%02x%02x%02x,%x\n" 4256 " compatible: %s", 4257 ddi_driver_name(sf->sf_dip), ddi_get_instance(sf->sf_dip), 4258 target->sft_port_wwn[0], target->sft_port_wwn[1], 4259 target->sft_port_wwn[2], target->sft_port_wwn[3], 4260 target->sft_port_wwn[4], target->sft_port_wwn[5], 4261 target->sft_port_wwn[6], target->sft_port_wwn[7], 4262 target->sft_lun.l, *compatible); 4263 #else 4264 sf_log(sf, CE_WARN, "%s%d: no driver for device " 4265 "@w%02x%02x%02x%02x%02x%02x%02x%02x,%x\n" 4266 " compatible: %s", 4267 ddi_driver_name(sf->sf_dip), ddi_get_instance(sf->sf_dip), 4268 target->sft_port_wwn[0], target->sft_port_wwn[1], 4269 target->sft_port_wwn[2], target->sft_port_wwn[3], 4270 target->sft_port_wwn[4], target->sft_port_wwn[5], 4271 target->sft_port_wwn[6], target->sft_port_wwn[7], 4272 target->sft_raid_lun, *compatible); 4273 #endif 4274 goto fail; 4275 } 4276 4277 /* allocate the node */ 4278 if (ndi_devi_alloc(sf->sf_dip, nname, 4279 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 4280 goto fail; 4281 } 4282 4283 /* decorate the node with compatible */ 4284 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 4285 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 4286 goto fail; 4287 } 4288 4289 /* add addressing properties to the node */ 4290 if (sf_create_props(cdip, target, lip_cnt) != 1) { 4291 goto fail; 4292 } 4293 4294 mutex_enter(&target->sft_mutex); 4295 if (target->sft_dip != NULL) { 4296 mutex_exit(&target->sft_mutex); 4297 goto fail; 4298 } 4299 target->sft_dip = cdip; 4300 mutex_exit(&target->sft_mutex); 4301 4302 if (ndi_devi_online_async(cdip, 0) != DDI_SUCCESS) { 4303 goto fail; 4304 } 4305 4306 scsi_hba_nodename_compatible_free(nname, compatible); 4307 return; 4308 4309 fail: 4310 scsi_hba_nodename_compatible_free(nname, compatible); 4311 if (cdip != NULL) { 4312 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP); 4313 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP); 4314 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, LIP_CNT_PROP); 4315 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, TARGET_PROP); 4316 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, LUN_PROP); 4317 if (ndi_devi_free(cdip) != NDI_SUCCESS) { 4318 sf_log(sf, CE_WARN, "ndi_devi_free failed\n"); 4319 } else { 4320 mutex_enter(&target->sft_mutex); 4321 if (cdip == target->sft_dip) { 4322 target->sft_dip = NULL; 4323 } 4324 mutex_exit(&target->sft_mutex); 4325 } 4326 } 4327 } 4328 4329 /* 4330 * create required properties, returning TRUE iff we succeed, else 4331 * returning FALSE 4332 */ 4333 static int 4334 sf_create_props(dev_info_t *cdip, struct sf_target *target, int lip_cnt) 4335 { 4336 int tgt_id = sf_alpa_to_switch[target->sft_al_pa]; 4337 4338 4339 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, 4340 cdip, NODE_WWN_PROP, target->sft_node_wwn, FC_WWN_SIZE) != 4341 DDI_PROP_SUCCESS) { 4342 return (FALSE); 4343 } 4344 4345 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, 4346 cdip, PORT_WWN_PROP, target->sft_port_wwn, FC_WWN_SIZE) != 4347 DDI_PROP_SUCCESS) { 4348 return (FALSE); 4349 } 4350 4351 if (ndi_prop_update_int(DDI_DEV_T_NONE, 4352 cdip, LIP_CNT_PROP, lip_cnt) != DDI_PROP_SUCCESS) { 4353 return (FALSE); 4354 } 4355 4356 if (ndi_prop_update_int(DDI_DEV_T_NONE, 4357 cdip, TARGET_PROP, tgt_id) != DDI_PROP_SUCCESS) { 4358 return (FALSE); 4359 } 4360 4361 #ifndef RAID_LUNS 4362 if (ndi_prop_update_int(DDI_DEV_T_NONE, 4363 cdip, LUN_PROP, target->sft_lun.l) != DDI_PROP_SUCCESS) { 4364 return (0); 4365 } 4366 #else 4367 if (ndi_prop_update_int(DDI_DEV_T_NONE, 4368 cdip, LUN_PROP, target->sft_raid_lun) != DDI_PROP_SUCCESS) { 4369 return (0); 4370 } 4371 #endif 4372 4373 return (TRUE); 4374 } 4375 4376 4377 /* 4378 * called by the transport to offline a target 4379 */ 4380 /* ARGSUSED */ 4381 static void 4382 sf_offline_target(struct sf *sf, struct sf_target *target) 4383 { 4384 dev_info_t *dip; 4385 struct sf_target *next_target = NULL; 4386 struct sf_hp_elem *elem; 4387 4388 ASSERT(mutex_owned(&sf->sf_mutex)); 4389 4390 if (sf_core && (sf_core & SF_CORE_OFFLINE_TARGET)) { 4391 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp); 4392 sf_core = 0; 4393 } 4394 4395 while (target != NULL) { 4396 sf_log(sf, CE_NOTE, 4397 "!target 0x%x al_pa 0x%x lun %" PRIx64 " offlined\n", 4398 sf_alpa_to_switch[target->sft_al_pa], 4399 target->sft_al_pa, SCSA_LUN(target)); 4400 mutex_enter(&target->sft_mutex); 4401 target->sft_state &= ~(SF_TARGET_BUSY|SF_TARGET_MARK); 4402 target->sft_state |= SF_TARGET_OFFLINE; 4403 mutex_exit(&target->sft_mutex); 4404 mutex_exit(&sf->sf_mutex); 4405 4406 /* XXXX if this is LUN 0, offline all other LUNs */ 4407 if (next_target || target->sft_lun.l == 0) 4408 next_target = target->sft_next_lun; 4409 4410 /* abort all cmds for this target */ 4411 sf_abort_all(sf, target, FALSE, sf->sf_lip_cnt, FALSE); 4412 4413 mutex_enter(&sf->sf_mutex); 4414 mutex_enter(&target->sft_mutex); 4415 if (target->sft_state & SF_TARGET_INIT_DONE) { 4416 dip = target->sft_dip; 4417 mutex_exit(&target->sft_mutex); 4418 mutex_exit(&sf->sf_mutex); 4419 (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, 4420 TARGET_PROP); 4421 (void) ndi_event_retrieve_cookie(sf->sf_event_hdl, 4422 dip, FCAL_REMOVE_EVENT, &sf_remove_eid, 4423 NDI_EVENT_NOPASS); 4424 (void) ndi_event_run_callbacks(sf->sf_event_hdl, 4425 target->sft_dip, sf_remove_eid, NULL); 4426 4427 elem = kmem_zalloc(sizeof (struct sf_hp_elem), 4428 KM_NOSLEEP); 4429 if (elem != NULL) { 4430 elem->dip = dip; 4431 elem->target = target; 4432 elem->what = SF_OFFLINE; 4433 mutex_enter(&sf->sf_hp_daemon_mutex); 4434 if (sf->sf_hp_elem_tail != NULL) { 4435 sf->sf_hp_elem_tail->next = elem; 4436 sf->sf_hp_elem_tail = elem; 4437 } else { 4438 sf->sf_hp_elem_head = 4439 sf->sf_hp_elem_tail = 4440 elem; 4441 } 4442 cv_signal(&sf->sf_hp_daemon_cv); 4443 mutex_exit(&sf->sf_hp_daemon_mutex); 4444 } else { 4445 /* don't do NDI_DEVI_REMOVE for now */ 4446 if (ndi_devi_offline(dip, 0) != NDI_SUCCESS) { 4447 SF_DEBUG(1, (sf, CE_WARN, 4448 "target %x lun %" PRIx64 ", " 4449 "device offline failed", 4450 sf_alpa_to_switch[target-> 4451 sft_al_pa], 4452 SCSA_LUN(target))); 4453 } else { 4454 SF_DEBUG(1, (sf, CE_NOTE, 4455 "target %x, lun %" PRIx64 ", " 4456 "device offline succeeded\n", 4457 sf_alpa_to_switch[target-> 4458 sft_al_pa], 4459 SCSA_LUN(target))); 4460 } 4461 } 4462 mutex_enter(&sf->sf_mutex); 4463 } else { 4464 mutex_exit(&target->sft_mutex); 4465 } 4466 target = next_target; 4467 } 4468 } 4469 4470 4471 /* 4472 * routine to get/set a capability 4473 * 4474 * returning: 4475 * 1 (TRUE) boolean capability is true (on get) 4476 * 0 (FALSE) invalid capability, can't set capability (on set), 4477 * or boolean capability is false (on get) 4478 * -1 (UNDEFINED) can't find capability (SCSA) or unsupported capability 4479 * 3 when getting SCSI version number 4480 * AL_PA when getting port initiator ID 4481 */ 4482 static int 4483 sf_commoncap(struct scsi_address *ap, char *cap, 4484 int val, int tgtonly, int doset) 4485 { 4486 struct sf *sf = ADDR2SF(ap); 4487 int cidx; 4488 int rval = FALSE; 4489 4490 4491 if (cap == NULL) { 4492 SF_DEBUG(3, (sf, CE_WARN, "sf_commoncap: invalid arg")); 4493 return (rval); 4494 } 4495 4496 /* get index of capability string */ 4497 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 4498 /* can't find capability */ 4499 return (UNDEFINED); 4500 } 4501 4502 if (doset) { 4503 /* 4504 * Process setcap request. 4505 */ 4506 4507 /* 4508 * At present, we can only set binary (0/1) values 4509 */ 4510 switch (cidx) { 4511 case SCSI_CAP_ARQ: /* can't set this capability */ 4512 break; 4513 default: 4514 SF_DEBUG(3, (sf, CE_WARN, 4515 "sf_setcap: unsupported %d", cidx)); 4516 rval = UNDEFINED; 4517 break; 4518 } 4519 4520 SF_DEBUG(4, (sf, CE_NOTE, 4521 "set cap: cap=%s,val=0x%x,tgtonly=0x%x" 4522 ",doset=0x%x,rval=%d\n", 4523 cap, val, tgtonly, doset, rval)); 4524 4525 } else { 4526 /* 4527 * Process getcap request. 4528 */ 4529 switch (cidx) { 4530 case SCSI_CAP_DMA_MAX: 4531 break; /* don't' have this capability */ 4532 case SCSI_CAP_INITIATOR_ID: 4533 rval = sf->sf_al_pa; 4534 break; 4535 case SCSI_CAP_ARQ: 4536 rval = TRUE; /* do have this capability */ 4537 break; 4538 case SCSI_CAP_RESET_NOTIFICATION: 4539 case SCSI_CAP_TAGGED_QING: 4540 rval = TRUE; /* do have this capability */ 4541 break; 4542 case SCSI_CAP_SCSI_VERSION: 4543 rval = 3; 4544 break; 4545 case SCSI_CAP_INTERCONNECT_TYPE: 4546 rval = INTERCONNECT_FIBRE; 4547 break; 4548 default: 4549 SF_DEBUG(4, (sf, CE_WARN, 4550 "sf_scsi_getcap: unsupported")); 4551 rval = UNDEFINED; 4552 break; 4553 } 4554 SF_DEBUG(4, (sf, CE_NOTE, 4555 "get cap: cap=%s,val=0x%x,tgtonly=0x%x," 4556 "doset=0x%x,rval=%d\n", 4557 cap, val, tgtonly, doset, rval)); 4558 } 4559 4560 return (rval); 4561 } 4562 4563 4564 /* 4565 * called by the transport to get a capability 4566 */ 4567 static int 4568 sf_getcap(struct scsi_address *ap, char *cap, int whom) 4569 { 4570 return (sf_commoncap(ap, cap, 0, whom, FALSE)); 4571 } 4572 4573 4574 /* 4575 * called by the transport to set a capability 4576 */ 4577 static int 4578 sf_setcap(struct scsi_address *ap, char *cap, int value, int whom) 4579 { 4580 return (sf_commoncap(ap, cap, value, whom, TRUE)); 4581 } 4582 4583 4584 /* 4585 * called by the transport to abort a target 4586 */ 4587 static int 4588 sf_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 4589 { 4590 struct sf *sf = ADDR2SF(ap); 4591 struct sf_target *target = ADDR2TARGET(ap); 4592 struct sf_pkt *cmd, *ncmd, *pcmd; 4593 struct fcal_packet *fpkt; 4594 int rval = 0, t, my_rval = FALSE; 4595 int old_target_state; 4596 int lip_cnt; 4597 int tgt_id; 4598 fc_frame_header_t *hp; 4599 int deferred_destroy; 4600 4601 deferred_destroy = 0; 4602 4603 if (pkt != NULL) { 4604 cmd = PKT2CMD(pkt); 4605 fpkt = cmd->cmd_fp_pkt; 4606 SF_DEBUG(2, (sf, CE_NOTE, "sf_abort packet %p\n", 4607 (void *)fpkt)); 4608 pcmd = NULL; 4609 mutex_enter(&sf->sf_cmd_mutex); 4610 ncmd = sf->sf_pkt_head; 4611 while (ncmd != NULL) { 4612 if (ncmd == cmd) { 4613 if (pcmd != NULL) { 4614 pcmd->cmd_next = cmd->cmd_next; 4615 } else { 4616 sf->sf_pkt_head = cmd->cmd_next; 4617 } 4618 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 4619 cmd->cmd_state = SF_STATE_IDLE; 4620 pkt->pkt_reason = CMD_ABORTED; 4621 pkt->pkt_statistics |= STAT_ABORTED; 4622 my_rval = TRUE; 4623 break; 4624 } else { 4625 pcmd = ncmd; 4626 ncmd = ncmd->cmd_next; 4627 } 4628 } 4629 mutex_exit(&sf->sf_cmd_mutex); 4630 if (ncmd == NULL) { 4631 mutex_enter(&cmd->cmd_abort_mutex); 4632 if (cmd->cmd_state == SF_STATE_ISSUED) { 4633 cmd->cmd_state = SF_STATE_ABORTING; 4634 cmd->cmd_timeout = sf_watchdog_time + 20; 4635 mutex_exit(&cmd->cmd_abort_mutex); 4636 /* call transport to abort command */ 4637 if (((rval = soc_abort(sf->sf_sochandle, 4638 sf->sf_socp, sf->sf_sochandle->fcal_portno, 4639 fpkt, 1)) == FCAL_ABORTED) || 4640 (rval == FCAL_ABORT_FAILED)) { 4641 my_rval = TRUE; 4642 pkt->pkt_reason = CMD_ABORTED; 4643 pkt->pkt_statistics |= STAT_ABORTED; 4644 cmd->cmd_state = SF_STATE_IDLE; 4645 } else if (rval == FCAL_BAD_ABORT) { 4646 cmd->cmd_timeout = sf_watchdog_time 4647 + 20; 4648 my_rval = FALSE; 4649 } else { 4650 SF_DEBUG(1, (sf, CE_NOTE, 4651 "Command Abort failed\n")); 4652 } 4653 } else { 4654 mutex_exit(&cmd->cmd_abort_mutex); 4655 } 4656 } 4657 } else { 4658 SF_DEBUG(2, (sf, CE_NOTE, "sf_abort target\n")); 4659 mutex_enter(&sf->sf_mutex); 4660 lip_cnt = sf->sf_lip_cnt; 4661 mutex_enter(&target->sft_mutex); 4662 if (target->sft_state & (SF_TARGET_BUSY | 4663 SF_TARGET_OFFLINE)) { 4664 mutex_exit(&target->sft_mutex); 4665 return (rval); 4666 } 4667 old_target_state = target->sft_state; 4668 target->sft_state |= SF_TARGET_BUSY; 4669 mutex_exit(&target->sft_mutex); 4670 mutex_exit(&sf->sf_mutex); 4671 4672 if ((pkt = sf_scsi_init_pkt(ap, NULL, NULL, 0, 4673 0, 0, 0, NULL, 0)) != NULL) { 4674 4675 cmd = PKT2CMD(pkt); 4676 cmd->cmd_block->fcp_cntl.cntl_abort_tsk = 1; 4677 cmd->cmd_fp_pkt->fcal_pkt_comp = NULL; 4678 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 4679 4680 /* prepare the packet for transport */ 4681 if (sf_prepare_pkt(sf, cmd, target) == TRAN_ACCEPT) { 4682 4683 cmd->cmd_state = SF_STATE_ISSUED; 4684 /* 4685 * call transport to send a pkt polled 4686 * 4687 * if that fails call the transport to abort it 4688 */ 4689 if (soc_transport_poll(sf->sf_sochandle, 4690 cmd->cmd_fp_pkt, SF_ABORT_TIMEOUT, 4691 CQ_REQUEST_1) == FCAL_TRANSPORT_SUCCESS) { 4692 (void) ddi_dma_sync( 4693 cmd->cmd_cr_pool->rsp_dma_handle, 4694 (off_t) 4695 ((caddr_t)cmd->cmd_rsp_block - 4696 cmd->cmd_cr_pool->rsp_base), 4697 FCP_MAX_RSP_IU_SIZE, 4698 DDI_DMA_SYNC_FORKERNEL); 4699 if (((struct fcp_rsp_info *) 4700 (&cmd->cmd_rsp_block-> 4701 fcp_response_len + 1))-> 4702 rsp_code == FCP_NO_FAILURE) { 4703 /* abort cmds for this targ */ 4704 sf_abort_all(sf, target, TRUE, 4705 lip_cnt, TRUE); 4706 } else { 4707 hp = &cmd->cmd_fp_pkt-> 4708 fcal_socal_request. 4709 sr_fc_frame_hdr; 4710 tgt_id = sf_alpa_to_switch[ 4711 (uchar_t)hp->d_id]; 4712 sf->sf_stats.tstats[tgt_id]. 4713 task_mgmt_failures++; 4714 SF_DEBUG(1, (sf, CE_NOTE, 4715 "Target %d Abort Task " 4716 "Set failed\n", hp->d_id)); 4717 } 4718 } else { 4719 mutex_enter(&cmd->cmd_abort_mutex); 4720 if (cmd->cmd_state == SF_STATE_ISSUED) { 4721 cmd->cmd_state = SF_STATE_ABORTING; 4722 cmd->cmd_timeout = sf_watchdog_time 4723 + 20; 4724 mutex_exit(&cmd->cmd_abort_mutex); 4725 if ((t = soc_abort(sf->sf_sochandle, 4726 sf->sf_socp, sf->sf_sochandle-> 4727 fcal_portno, cmd->cmd_fp_pkt, 1)) != 4728 FCAL_ABORTED && 4729 (t != FCAL_ABORT_FAILED)) { 4730 sf_log(sf, CE_NOTE, 4731 "sf_abort failed, " 4732 "initiating LIP\n"); 4733 sf_force_lip(sf); 4734 deferred_destroy = 1; 4735 } 4736 } else { 4737 mutex_exit(&cmd->cmd_abort_mutex); 4738 } 4739 } 4740 } 4741 if (!deferred_destroy) { 4742 cmd->cmd_fp_pkt->fcal_pkt_comp = 4743 sf_cmd_callback; 4744 cmd->cmd_block->fcp_cntl.cntl_abort_tsk = 0; 4745 sf_scsi_destroy_pkt(ap, pkt); 4746 my_rval = TRUE; 4747 } 4748 } 4749 mutex_enter(&sf->sf_mutex); 4750 if (lip_cnt == sf->sf_lip_cnt) { 4751 mutex_enter(&target->sft_mutex); 4752 target->sft_state = old_target_state; 4753 mutex_exit(&target->sft_mutex); 4754 } 4755 mutex_exit(&sf->sf_mutex); 4756 } 4757 return (my_rval); 4758 } 4759 4760 4761 /* 4762 * called by the transport and internally to reset a target 4763 */ 4764 static int 4765 sf_reset(struct scsi_address *ap, int level) 4766 { 4767 struct scsi_pkt *pkt; 4768 struct fcal_packet *fpkt; 4769 struct sf *sf = ADDR2SF(ap); 4770 struct sf_target *target = ADDR2TARGET(ap), *ntarget; 4771 struct sf_pkt *cmd; 4772 int rval = FALSE, t; 4773 int lip_cnt; 4774 int tgt_id, ret; 4775 fc_frame_header_t *hp; 4776 int deferred_destroy; 4777 4778 /* We don't support RESET_LUN yet. */ 4779 if (level == RESET_TARGET) { 4780 struct sf_reset_list *p; 4781 4782 if ((p = kmem_alloc(sizeof (struct sf_reset_list), KM_NOSLEEP)) 4783 == NULL) 4784 return (rval); 4785 4786 SF_DEBUG(2, (sf, CE_NOTE, "sf_reset target\n")); 4787 mutex_enter(&sf->sf_mutex); 4788 /* All target resets go to LUN 0 */ 4789 if (target->sft_lun.l) { 4790 target = sf_lookup_target(sf, target->sft_port_wwn, 0); 4791 } 4792 mutex_enter(&target->sft_mutex); 4793 if (target->sft_state & (SF_TARGET_BUSY | 4794 SF_TARGET_OFFLINE)) { 4795 mutex_exit(&target->sft_mutex); 4796 mutex_exit(&sf->sf_mutex); 4797 kmem_free(p, sizeof (struct sf_reset_list)); 4798 return (rval); 4799 } 4800 lip_cnt = sf->sf_lip_cnt; 4801 target->sft_state |= SF_TARGET_BUSY; 4802 for (ntarget = target->sft_next_lun; 4803 ntarget; 4804 ntarget = ntarget->sft_next_lun) { 4805 mutex_enter(&ntarget->sft_mutex); 4806 /* 4807 * XXXX If we supported RESET_LUN we should check here 4808 * to see if any LUN were being reset and somehow fail 4809 * that operation. 4810 */ 4811 ntarget->sft_state |= SF_TARGET_BUSY; 4812 mutex_exit(&ntarget->sft_mutex); 4813 } 4814 mutex_exit(&target->sft_mutex); 4815 mutex_exit(&sf->sf_mutex); 4816 4817 deferred_destroy = 0; 4818 if ((pkt = sf_scsi_init_pkt(ap, NULL, NULL, 0, 4819 0, 0, 0, NULL, 0)) != NULL) { 4820 cmd = PKT2CMD(pkt); 4821 cmd->cmd_block->fcp_cntl.cntl_reset = 1; 4822 cmd->cmd_fp_pkt->fcal_pkt_comp = NULL; 4823 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 4824 4825 /* prepare the packet for transport */ 4826 if (sf_prepare_pkt(sf, cmd, target) == TRAN_ACCEPT) { 4827 /* call transport to send a pkt polled */ 4828 cmd->cmd_state = SF_STATE_ISSUED; 4829 if ((ret = soc_transport_poll(sf->sf_sochandle, 4830 cmd->cmd_fp_pkt, SF_ABORT_TIMEOUT, 4831 CQ_REQUEST_1)) == FCAL_TRANSPORT_SUCCESS) { 4832 (void) ddi_dma_sync(cmd->cmd_cr_pool-> 4833 rsp_dma_handle, (caddr_t)cmd-> 4834 cmd_rsp_block - cmd->cmd_cr_pool-> 4835 rsp_base, FCP_MAX_RSP_IU_SIZE, 4836 DDI_DMA_SYNC_FORKERNEL); 4837 fpkt = cmd->cmd_fp_pkt; 4838 if ((fpkt->fcal_pkt_status == 4839 FCAL_STATUS_OK) && 4840 (((struct fcp_rsp_info *) 4841 (&cmd->cmd_rsp_block-> 4842 fcp_response_len + 1))-> 4843 rsp_code == FCP_NO_FAILURE)) { 4844 sf_log(sf, CE_NOTE, 4845 "!sf%d: Target 0x%x Reset " 4846 "successful\n", 4847 ddi_get_instance(\ 4848 sf->sf_dip), 4849 sf_alpa_to_switch[ 4850 target->sft_al_pa]); 4851 rval = TRUE; 4852 } else { 4853 hp = &cmd->cmd_fp_pkt-> 4854 fcal_socal_request. 4855 sr_fc_frame_hdr; 4856 tgt_id = sf_alpa_to_switch[ 4857 (uchar_t)hp->d_id]; 4858 sf->sf_stats.tstats[tgt_id]. 4859 task_mgmt_failures++; 4860 sf_log(sf, CE_NOTE, 4861 "!sf%d: Target 0x%x " 4862 "Reset failed." 4863 "Status code 0x%x " 4864 "Resp code 0x%x\n", 4865 ddi_get_instance(\ 4866 sf->sf_dip), 4867 tgt_id, 4868 fpkt->fcal_pkt_status, 4869 ((struct fcp_rsp_info *) 4870 (&cmd->cmd_rsp_block-> 4871 fcp_response_len + 1))-> 4872 rsp_code); 4873 } 4874 } else { 4875 sf_log(sf, CE_NOTE, "!sf%d: Target " 4876 "0x%x Reset Failed. Ret=%x\n", 4877 ddi_get_instance(sf->sf_dip), 4878 sf_alpa_to_switch[ 4879 target->sft_al_pa], ret); 4880 mutex_enter(&cmd->cmd_abort_mutex); 4881 if (cmd->cmd_state == SF_STATE_ISSUED) { 4882 /* call the transport to abort a cmd */ 4883 cmd->cmd_timeout = sf_watchdog_time 4884 + 20; 4885 cmd->cmd_state = SF_STATE_ABORTING; 4886 mutex_exit(&cmd->cmd_abort_mutex); 4887 if (((t = soc_abort(sf->sf_sochandle, 4888 sf->sf_socp, 4889 sf->sf_sochandle->fcal_portno, 4890 cmd->cmd_fp_pkt, 1)) != 4891 FCAL_ABORTED) && 4892 (t != FCAL_ABORT_FAILED)) { 4893 sf_log(sf, CE_NOTE, 4894 "!sf%d: Target 0x%x Reset " 4895 "failed. Abort Failed, " 4896 "forcing LIP\n", 4897 ddi_get_instance( 4898 sf->sf_dip), 4899 sf_alpa_to_switch[ 4900 target->sft_al_pa]); 4901 sf_force_lip(sf); 4902 rval = TRUE; 4903 deferred_destroy = 1; 4904 } 4905 } else { 4906 mutex_exit 4907 (&cmd->cmd_abort_mutex); 4908 } 4909 } 4910 } 4911 /* 4912 * Defer releasing the packet if we abort returned with 4913 * a BAD_ABORT or timed out, because there is a 4914 * possibility that the ucode might return it. 4915 * We wait for at least 20s and let it be released 4916 * by the sf_watch thread 4917 */ 4918 if (!deferred_destroy) { 4919 cmd->cmd_block->fcp_cntl.cntl_reset = 0; 4920 cmd->cmd_fp_pkt->fcal_pkt_comp = 4921 sf_cmd_callback; 4922 cmd->cmd_state = SF_STATE_IDLE; 4923 /* for cache */ 4924 sf_scsi_destroy_pkt(ap, pkt); 4925 } 4926 } else { 4927 cmn_err(CE_WARN, "!sf%d: Target 0x%x Reset Failed. " 4928 "Resource allocation error.\n", 4929 ddi_get_instance(sf->sf_dip), 4930 sf_alpa_to_switch[target->sft_al_pa]); 4931 } 4932 mutex_enter(&sf->sf_mutex); 4933 if ((rval == TRUE) && (lip_cnt == sf->sf_lip_cnt)) { 4934 p->target = target; 4935 p->lip_cnt = lip_cnt; 4936 p->timeout = ddi_get_lbolt() + 4937 drv_usectohz(SF_TARGET_RESET_DELAY); 4938 p->next = sf->sf_reset_list; 4939 sf->sf_reset_list = p; 4940 mutex_exit(&sf->sf_mutex); 4941 mutex_enter(&sf_global_mutex); 4942 if (sf_reset_timeout_id == 0) { 4943 sf_reset_timeout_id = timeout( 4944 sf_check_reset_delay, NULL, 4945 drv_usectohz(SF_TARGET_RESET_DELAY)); 4946 } 4947 mutex_exit(&sf_global_mutex); 4948 } else { 4949 if (lip_cnt == sf->sf_lip_cnt) { 4950 mutex_enter(&target->sft_mutex); 4951 target->sft_state &= ~SF_TARGET_BUSY; 4952 for (ntarget = target->sft_next_lun; 4953 ntarget; 4954 ntarget = ntarget->sft_next_lun) { 4955 mutex_enter(&ntarget->sft_mutex); 4956 ntarget->sft_state &= ~SF_TARGET_BUSY; 4957 mutex_exit(&ntarget->sft_mutex); 4958 } 4959 mutex_exit(&target->sft_mutex); 4960 } 4961 mutex_exit(&sf->sf_mutex); 4962 kmem_free(p, sizeof (struct sf_reset_list)); 4963 } 4964 } else { 4965 mutex_enter(&sf->sf_mutex); 4966 if ((sf->sf_state == SF_STATE_OFFLINE) && 4967 (sf_watchdog_time < sf->sf_timer)) { 4968 /* 4969 * We are currently in a lip, so let this one 4970 * finish before forcing another one. 4971 */ 4972 mutex_exit(&sf->sf_mutex); 4973 return (TRUE); 4974 } 4975 mutex_exit(&sf->sf_mutex); 4976 sf_log(sf, CE_NOTE, "!sf:Target driver initiated lip\n"); 4977 sf_force_lip(sf); 4978 rval = TRUE; 4979 } 4980 return (rval); 4981 } 4982 4983 4984 /* 4985 * abort all commands for a target 4986 * 4987 * if try_abort is set then send an abort 4988 * if abort is set then this is abort, else this is a reset 4989 */ 4990 static void 4991 sf_abort_all(struct sf *sf, struct sf_target *target, int abort, int 4992 lip_cnt, int try_abort) 4993 { 4994 struct sf_target *ntarget; 4995 struct sf_pkt *cmd, *head = NULL, *tail = NULL, *pcmd = NULL, *tcmd; 4996 struct fcal_packet *fpkt; 4997 struct scsi_pkt *pkt; 4998 int rval = FCAL_ABORTED; 4999 5000 /* 5001 * First pull all commands for all LUNs on this target out of the 5002 * overflow list. We can tell it's the same target by comparing 5003 * the node WWN. 5004 */ 5005 mutex_enter(&sf->sf_mutex); 5006 if (lip_cnt == sf->sf_lip_cnt) { 5007 mutex_enter(&sf->sf_cmd_mutex); 5008 cmd = sf->sf_pkt_head; 5009 while (cmd != NULL) { 5010 ntarget = ADDR2TARGET(&cmd->cmd_pkt-> 5011 pkt_address); 5012 if (ntarget == target) { 5013 if (pcmd != NULL) 5014 pcmd->cmd_next = cmd->cmd_next; 5015 else 5016 sf->sf_pkt_head = cmd->cmd_next; 5017 if (sf->sf_pkt_tail == cmd) { 5018 sf->sf_pkt_tail = pcmd; 5019 if (pcmd != NULL) 5020 pcmd->cmd_next = NULL; 5021 } 5022 tcmd = cmd->cmd_next; 5023 if (head == NULL) { 5024 head = cmd; 5025 tail = cmd; 5026 } else { 5027 tail->cmd_next = cmd; 5028 tail = cmd; 5029 } 5030 cmd->cmd_next = NULL; 5031 cmd = tcmd; 5032 } else { 5033 pcmd = cmd; 5034 cmd = cmd->cmd_next; 5035 } 5036 } 5037 mutex_exit(&sf->sf_cmd_mutex); 5038 } 5039 mutex_exit(&sf->sf_mutex); 5040 5041 /* 5042 * Now complete all the commands on our list. In the process, 5043 * the completion routine may take the commands off the target 5044 * lists. 5045 */ 5046 cmd = head; 5047 while (cmd != NULL) { 5048 pkt = cmd->cmd_pkt; 5049 if (abort) { 5050 pkt->pkt_reason = CMD_ABORTED; 5051 pkt->pkt_statistics |= STAT_ABORTED; 5052 } else { 5053 pkt->pkt_reason = CMD_RESET; 5054 pkt->pkt_statistics |= STAT_DEV_RESET; 5055 } 5056 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 5057 cmd->cmd_state = SF_STATE_IDLE; 5058 cmd = cmd->cmd_next; 5059 /* 5060 * call the packet completion routine only for 5061 * non-polled commands. Ignore the polled commands as 5062 * they timeout and will be handled differently 5063 */ 5064 if ((pkt->pkt_comp) && !(pkt->pkt_flags & FLAG_NOINTR)) 5065 (*pkt->pkt_comp)(pkt); 5066 5067 } 5068 5069 /* 5070 * Finally get all outstanding commands for each LUN, and abort them if 5071 * they've been issued, and call the completion routine. 5072 * For the case where sf_offline_target is called from sf_watch 5073 * due to a Offline Timeout, it is quite possible that the soc+ 5074 * ucode is hosed and therefore cannot return the commands. 5075 * Clear up all the issued commands as well. 5076 * Try_abort will be false only if sf_abort_all is coming from 5077 * sf_target_offline. 5078 */ 5079 5080 if (try_abort || sf->sf_state == SF_STATE_OFFLINE) { 5081 mutex_enter(&target->sft_pkt_mutex); 5082 cmd = tcmd = target->sft_pkt_head; 5083 while (cmd != (struct sf_pkt *)&target->sft_pkt_head) { 5084 fpkt = cmd->cmd_fp_pkt; 5085 pkt = cmd->cmd_pkt; 5086 mutex_enter(&cmd->cmd_abort_mutex); 5087 if ((cmd->cmd_state == SF_STATE_ISSUED) && 5088 (fpkt->fcal_cmd_state & 5089 FCAL_CMD_IN_TRANSPORT) && 5090 ((fpkt->fcal_cmd_state & FCAL_CMD_COMPLETE) == 5091 0) && !(pkt->pkt_flags & FLAG_NOINTR)) { 5092 cmd->cmd_state = SF_STATE_ABORTING; 5093 cmd->cmd_timeout = sf_watchdog_time + 5094 cmd->cmd_pkt->pkt_time + 20; 5095 mutex_exit(&cmd->cmd_abort_mutex); 5096 mutex_exit(&target->sft_pkt_mutex); 5097 if (try_abort) { 5098 /* call the transport to abort a pkt */ 5099 rval = soc_abort(sf->sf_sochandle, 5100 sf->sf_socp, 5101 sf->sf_sochandle->fcal_portno, 5102 fpkt, 1); 5103 } 5104 if ((rval == FCAL_ABORTED) || 5105 (rval == FCAL_ABORT_FAILED)) { 5106 if (abort) { 5107 pkt->pkt_reason = CMD_ABORTED; 5108 pkt->pkt_statistics |= 5109 STAT_ABORTED; 5110 } else { 5111 pkt->pkt_reason = CMD_RESET; 5112 pkt->pkt_statistics |= 5113 STAT_DEV_RESET; 5114 } 5115 cmd->cmd_state = SF_STATE_IDLE; 5116 if (pkt->pkt_comp) 5117 (*pkt->pkt_comp)(pkt); 5118 } 5119 mutex_enter(&sf->sf_mutex); 5120 if (lip_cnt != sf->sf_lip_cnt) { 5121 mutex_exit(&sf->sf_mutex); 5122 return; 5123 } 5124 mutex_exit(&sf->sf_mutex); 5125 mutex_enter(&target->sft_pkt_mutex); 5126 cmd = target->sft_pkt_head; 5127 } else { 5128 mutex_exit(&cmd->cmd_abort_mutex); 5129 cmd = cmd->cmd_forw; 5130 } 5131 } 5132 mutex_exit(&target->sft_pkt_mutex); 5133 } 5134 } 5135 5136 5137 /* 5138 * called by the transport to start a packet 5139 */ 5140 static int 5141 sf_start(struct scsi_address *ap, struct scsi_pkt *pkt) 5142 { 5143 struct sf *sf = ADDR2SF(ap); 5144 struct sf_target *target = ADDR2TARGET(ap); 5145 struct sf_pkt *cmd = PKT2CMD(pkt); 5146 int rval; 5147 5148 5149 SF_DEBUG(6, (sf, CE_NOTE, "sf_start\n")); 5150 5151 if (cmd->cmd_state == SF_STATE_ISSUED) { 5152 cmn_err(CE_PANIC, "sf: issuing packet twice 0x%p\n", 5153 (void *)cmd); 5154 } 5155 5156 /* prepare the packet for transport */ 5157 if ((rval = sf_prepare_pkt(sf, cmd, target)) != TRAN_ACCEPT) { 5158 return (rval); 5159 } 5160 5161 if (target->sft_state & (SF_TARGET_BUSY|SF_TARGET_OFFLINE)) { 5162 if (target->sft_state & SF_TARGET_OFFLINE) { 5163 return (TRAN_FATAL_ERROR); 5164 } 5165 if (pkt->pkt_flags & FLAG_NOINTR) { 5166 return (TRAN_BUSY); 5167 } 5168 mutex_enter(&sf->sf_cmd_mutex); 5169 sf->sf_use_lock = TRUE; 5170 goto enque; 5171 } 5172 5173 5174 /* if no interrupts then do polled I/O */ 5175 if (pkt->pkt_flags & FLAG_NOINTR) { 5176 return (sf_dopoll(sf, cmd)); 5177 } 5178 5179 /* regular interrupt-driven I/O */ 5180 5181 if (!sf->sf_use_lock) { 5182 5183 /* locking no needed */ 5184 5185 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 5186 sf_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 5187 cmd->cmd_state = SF_STATE_ISSUED; 5188 5189 /* call the transport to send a pkt */ 5190 if (soc_transport(sf->sf_sochandle, cmd->cmd_fp_pkt, 5191 FCAL_NOSLEEP, CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) { 5192 cmd->cmd_state = SF_STATE_IDLE; 5193 return (TRAN_BADPKT); 5194 } 5195 return (TRAN_ACCEPT); 5196 } 5197 5198 /* regular I/O using locking */ 5199 5200 mutex_enter(&sf->sf_cmd_mutex); 5201 if ((sf->sf_ncmds >= sf->sf_throttle) || 5202 (sf->sf_pkt_head != NULL)) { 5203 enque: 5204 /* 5205 * either we're throttling back or there are already commands 5206 * on the queue, so enqueue this one for later 5207 */ 5208 cmd->cmd_flags |= CFLAG_IN_QUEUE; 5209 if (sf->sf_pkt_head != NULL) { 5210 /* add to the queue */ 5211 sf->sf_pkt_tail->cmd_next = cmd; 5212 cmd->cmd_next = NULL; 5213 sf->sf_pkt_tail = cmd; 5214 } else { 5215 /* this is the first entry in the queue */ 5216 sf->sf_pkt_head = sf->sf_pkt_tail = cmd; 5217 cmd->cmd_next = NULL; 5218 } 5219 mutex_exit(&sf->sf_cmd_mutex); 5220 return (TRAN_ACCEPT); 5221 } 5222 5223 /* 5224 * start this packet now 5225 */ 5226 5227 /* still have cmd mutex */ 5228 return (sf_start_internal(sf, cmd)); 5229 } 5230 5231 5232 /* 5233 * internal routine to start a packet from the queue now 5234 * 5235 * enter with cmd mutex held and leave with it released 5236 */ 5237 static int 5238 sf_start_internal(struct sf *sf, struct sf_pkt *cmd) 5239 { 5240 /* we have the cmd mutex */ 5241 sf->sf_ncmds++; 5242 mutex_exit(&sf->sf_cmd_mutex); 5243 5244 ASSERT(cmd->cmd_state != SF_STATE_ISSUED); 5245 SF_DEBUG(6, (sf, CE_NOTE, "sf_start_internal\n")); 5246 5247 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? sf_watchdog_time + 5248 cmd->cmd_pkt->pkt_time : 0; 5249 cmd->cmd_state = SF_STATE_ISSUED; 5250 5251 /* call transport to send the pkt */ 5252 if (soc_transport(sf->sf_sochandle, cmd->cmd_fp_pkt, FCAL_NOSLEEP, 5253 CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) { 5254 cmd->cmd_state = SF_STATE_IDLE; 5255 mutex_enter(&sf->sf_cmd_mutex); 5256 sf->sf_ncmds--; 5257 mutex_exit(&sf->sf_cmd_mutex); 5258 return (TRAN_BADPKT); 5259 } 5260 return (TRAN_ACCEPT); 5261 } 5262 5263 5264 /* 5265 * prepare a packet for transport 5266 */ 5267 static int 5268 sf_prepare_pkt(struct sf *sf, struct sf_pkt *cmd, struct sf_target *target) 5269 { 5270 struct fcp_cmd *fcmd = cmd->cmd_block; 5271 5272 /* XXXX Need to set the LUN ? */ 5273 bcopy((caddr_t)&target->sft_lun.b, 5274 (caddr_t)&fcmd->fcp_ent_addr, 5275 FCP_LUN_SIZE); 5276 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 5277 cmd->cmd_pkt->pkt_state = 0; 5278 cmd->cmd_pkt->pkt_statistics = 0; 5279 5280 5281 if ((cmd->cmd_pkt->pkt_comp == NULL) && 5282 ((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0)) { 5283 return (TRAN_BADPKT); 5284 } 5285 5286 /* invalidate imp field(s) of rsp block */ 5287 cmd->cmd_rsp_block->fcp_u.i_fcp_status = SF_BAD_DMA_MAGIC; 5288 5289 /* set up amt of I/O to do */ 5290 if (cmd->cmd_flags & CFLAG_DMAVALID) { 5291 cmd->cmd_pkt->pkt_resid = cmd->cmd_dmacount; 5292 if (cmd->cmd_flags & CFLAG_CMDIOPB) { 5293 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0, 5294 DDI_DMA_SYNC_FORDEV); 5295 } 5296 } else { 5297 cmd->cmd_pkt->pkt_resid = 0; 5298 } 5299 5300 /* set up the Tagged Queuing type */ 5301 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 5302 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 5303 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 5304 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 5305 } 5306 5307 /* 5308 * Sync the cmd segment 5309 */ 5310 (void) ddi_dma_sync(cmd->cmd_cr_pool->cmd_dma_handle, 5311 (caddr_t)fcmd - cmd->cmd_cr_pool->cmd_base, 5312 sizeof (struct fcp_cmd), DDI_DMA_SYNC_FORDEV); 5313 5314 sf_fill_ids(sf, cmd, target); 5315 return (TRAN_ACCEPT); 5316 } 5317 5318 5319 /* 5320 * fill in packet hdr source and destination IDs and hdr byte count 5321 */ 5322 static void 5323 sf_fill_ids(struct sf *sf, struct sf_pkt *cmd, struct sf_target *target) 5324 { 5325 struct fcal_packet *fpkt = cmd->cmd_fp_pkt; 5326 fc_frame_header_t *hp; 5327 5328 5329 hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr; 5330 hp->d_id = target->sft_al_pa; 5331 hp->s_id = sf->sf_al_pa; 5332 fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = 5333 cmd->cmd_dmacookie.dmac_size; 5334 } 5335 5336 5337 /* 5338 * do polled I/O using transport 5339 */ 5340 static int 5341 sf_dopoll(struct sf *sf, struct sf_pkt *cmd) 5342 { 5343 int timeout; 5344 int rval; 5345 5346 5347 mutex_enter(&sf->sf_cmd_mutex); 5348 sf->sf_ncmds++; 5349 mutex_exit(&sf->sf_cmd_mutex); 5350 5351 timeout = cmd->cmd_pkt->pkt_time ? cmd->cmd_pkt->pkt_time 5352 : SF_POLL_TIMEOUT; 5353 cmd->cmd_timeout = 0; 5354 cmd->cmd_fp_pkt->fcal_pkt_comp = NULL; 5355 cmd->cmd_state = SF_STATE_ISSUED; 5356 5357 /* call transport to send a pkt polled */ 5358 rval = soc_transport_poll(sf->sf_sochandle, cmd->cmd_fp_pkt, 5359 timeout*1000000, CQ_REQUEST_1); 5360 mutex_enter(&cmd->cmd_abort_mutex); 5361 cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback; 5362 if (rval != FCAL_TRANSPORT_SUCCESS) { 5363 if (rval == FCAL_TRANSPORT_TIMEOUT) { 5364 cmd->cmd_state = SF_STATE_ABORTING; 5365 mutex_exit(&cmd->cmd_abort_mutex); 5366 (void) sf_target_timeout(sf, cmd); 5367 } else { 5368 mutex_exit(&cmd->cmd_abort_mutex); 5369 } 5370 cmd->cmd_state = SF_STATE_IDLE; 5371 cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback; 5372 mutex_enter(&sf->sf_cmd_mutex); 5373 sf->sf_ncmds--; 5374 mutex_exit(&sf->sf_cmd_mutex); 5375 return (TRAN_BADPKT); 5376 } 5377 mutex_exit(&cmd->cmd_abort_mutex); 5378 cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback; 5379 sf_cmd_callback(cmd->cmd_fp_pkt); 5380 return (TRAN_ACCEPT); 5381 } 5382 5383 5384 /* a shortcut for defining debug messages below */ 5385 #ifdef DEBUG 5386 #define SF_DMSG1(s) msg1 = s 5387 #else 5388 #define SF_DMSG1(s) /* do nothing */ 5389 #endif 5390 5391 5392 /* 5393 * the pkt_comp callback for command packets 5394 */ 5395 static void 5396 sf_cmd_callback(struct fcal_packet *fpkt) 5397 { 5398 struct sf_pkt *cmd = (struct sf_pkt *)fpkt->fcal_pkt_private; 5399 struct scsi_pkt *pkt = cmd->cmd_pkt; 5400 struct sf *sf = ADDR2SF(&pkt->pkt_address); 5401 struct sf_target *target = ADDR2TARGET(&pkt->pkt_address); 5402 struct fcp_rsp *rsp; 5403 char *msg1 = NULL; 5404 char *msg2 = NULL; 5405 short ncmds; 5406 int tgt_id; 5407 int good_scsi_status = TRUE; 5408 5409 5410 5411 if (cmd->cmd_state == SF_STATE_IDLE) { 5412 cmn_err(CE_PANIC, "sf: completing idle packet 0x%p\n", 5413 (void *)cmd); 5414 } 5415 5416 mutex_enter(&cmd->cmd_abort_mutex); 5417 if (cmd->cmd_state == SF_STATE_ABORTING) { 5418 /* cmd already being aborted -- nothing to do */ 5419 mutex_exit(&cmd->cmd_abort_mutex); 5420 return; 5421 } 5422 5423 cmd->cmd_state = SF_STATE_IDLE; 5424 mutex_exit(&cmd->cmd_abort_mutex); 5425 5426 if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) { 5427 5428 (void) ddi_dma_sync(cmd->cmd_cr_pool->rsp_dma_handle, 5429 (caddr_t)cmd->cmd_rsp_block - cmd->cmd_cr_pool->rsp_base, 5430 FCP_MAX_RSP_IU_SIZE, DDI_DMA_SYNC_FORKERNEL); 5431 5432 rsp = (struct fcp_rsp *)cmd->cmd_rsp_block; 5433 5434 if (rsp->fcp_u.i_fcp_status == SF_BAD_DMA_MAGIC) { 5435 5436 if (sf_core && (sf_core & SF_CORE_BAD_DMA)) { 5437 sf_token = (int *)(uintptr_t) 5438 fpkt->fcal_socal_request.\ 5439 sr_soc_hdr.sh_request_token; 5440 (void) soc_take_core(sf->sf_sochandle, 5441 sf->sf_socp); 5442 } 5443 5444 pkt->pkt_reason = CMD_INCOMPLETE; 5445 pkt->pkt_state = STATE_GOT_BUS; 5446 pkt->pkt_statistics |= STAT_ABORTED; 5447 5448 } else { 5449 5450 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 5451 STATE_SENT_CMD | STATE_GOT_STATUS; 5452 pkt->pkt_resid = 0; 5453 if (cmd->cmd_flags & CFLAG_DMAVALID) { 5454 pkt->pkt_state |= STATE_XFERRED_DATA; 5455 } 5456 5457 if ((pkt->pkt_scbp != NULL) && 5458 ((*(pkt->pkt_scbp) = 5459 rsp->fcp_u.fcp_status.scsi_status) 5460 != STATUS_GOOD)) { 5461 good_scsi_status = FALSE; 5462 /* 5463 * The next two checks make sure that if there 5464 * is no sense data or a valid response and 5465 * the command came back with check condition, 5466 * the command should be retried 5467 */ 5468 if (!rsp->fcp_u.fcp_status.rsp_len_set && 5469 !rsp->fcp_u.fcp_status.sense_len_set) { 5470 pkt->pkt_state &= ~STATE_XFERRED_DATA; 5471 pkt->pkt_resid = cmd->cmd_dmacount; 5472 } 5473 } 5474 5475 if ((cmd->cmd_flags & CFLAG_CMDIOPB) && 5476 (pkt->pkt_state & STATE_XFERRED_DATA)) { 5477 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 5478 (uint_t)0, DDI_DMA_SYNC_FORCPU); 5479 } 5480 /* 5481 * Update the transfer resid, if appropriate 5482 */ 5483 if (rsp->fcp_u.fcp_status.resid_over || 5484 rsp->fcp_u.fcp_status.resid_under) 5485 pkt->pkt_resid = rsp->fcp_resid; 5486 5487 /* 5488 * Check to see if the SCSI command failed. 5489 * 5490 */ 5491 5492 /* 5493 * First see if we got a FCP protocol error. 5494 */ 5495 if (rsp->fcp_u.fcp_status.rsp_len_set) { 5496 struct fcp_rsp_info *bep; 5497 5498 bep = (struct fcp_rsp_info *) 5499 (&rsp->fcp_response_len + 1); 5500 if (bep->rsp_code != FCP_NO_FAILURE) { 5501 pkt->pkt_reason = CMD_TRAN_ERR; 5502 tgt_id = pkt->pkt_address.a_target; 5503 switch (bep->rsp_code) { 5504 case FCP_CMND_INVALID: 5505 SF_DMSG1("FCP_RSP FCP_CMND " 5506 "fields invalid"); 5507 break; 5508 case FCP_TASK_MGMT_NOT_SUPPTD: 5509 SF_DMSG1("FCP_RSP Task" 5510 "Management Function" 5511 "Not Supported"); 5512 break; 5513 case FCP_TASK_MGMT_FAILED: 5514 SF_DMSG1("FCP_RSP Task " 5515 "Management Function" 5516 "Failed"); 5517 sf->sf_stats.tstats[tgt_id]. 5518 task_mgmt_failures++; 5519 break; 5520 case FCP_DATA_RO_MISMATCH: 5521 SF_DMSG1("FCP_RSP FCP_DATA RO " 5522 "mismatch with " 5523 "FCP_XFER_RDY DATA_RO"); 5524 sf->sf_stats.tstats[tgt_id]. 5525 data_ro_mismatches++; 5526 break; 5527 case FCP_DL_LEN_MISMATCH: 5528 SF_DMSG1("FCP_RSP FCP_DATA " 5529 "length " 5530 "different than BURST_LEN"); 5531 sf->sf_stats.tstats[tgt_id]. 5532 dl_len_mismatches++; 5533 break; 5534 default: 5535 SF_DMSG1("FCP_RSP invalid " 5536 "RSP_CODE"); 5537 break; 5538 } 5539 } 5540 } 5541 5542 /* 5543 * See if we got a SCSI error with sense data 5544 */ 5545 if (rsp->fcp_u.fcp_status.sense_len_set) { 5546 uchar_t rqlen = min(rsp->fcp_sense_len, 5547 sizeof (struct scsi_extended_sense)); 5548 caddr_t sense = (caddr_t)rsp + 5549 sizeof (struct fcp_rsp) + 5550 rsp->fcp_response_len; 5551 struct scsi_arq_status *arq; 5552 struct scsi_extended_sense *sensep = 5553 (struct scsi_extended_sense *)sense; 5554 5555 if (rsp->fcp_u.fcp_status.scsi_status != 5556 STATUS_GOOD) { 5557 if (rsp->fcp_u.fcp_status.scsi_status 5558 == STATUS_CHECK) { 5559 if (sensep->es_key == 5560 KEY_RECOVERABLE_ERROR) 5561 good_scsi_status = 1; 5562 if (sensep->es_key == 5563 KEY_UNIT_ATTENTION && 5564 sensep->es_add_code == 0x3f && 5565 sensep->es_qual_code == 0x0e) { 5566 /* REPORT_LUNS_HAS_CHANGED */ 5567 sf_log(sf, CE_NOTE, 5568 "!REPORT_LUNS_HAS_CHANGED\n"); 5569 sf_force_lip(sf); 5570 } 5571 } 5572 } 5573 5574 if ((pkt->pkt_scbp != NULL) && 5575 (cmd->cmd_scblen >= 5576 sizeof (struct scsi_arq_status))) { 5577 5578 pkt->pkt_state |= STATE_ARQ_DONE; 5579 5580 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 5581 /* 5582 * copy out sense information 5583 */ 5584 bcopy(sense, (caddr_t)&arq->sts_sensedata, 5585 rqlen); 5586 arq->sts_rqpkt_resid = 5587 sizeof (struct scsi_extended_sense) - 5588 rqlen; 5589 *((uchar_t *)&arq->sts_rqpkt_status) = 5590 STATUS_GOOD; 5591 arq->sts_rqpkt_reason = 0; 5592 arq->sts_rqpkt_statistics = 0; 5593 arq->sts_rqpkt_state = STATE_GOT_BUS | 5594 STATE_GOT_TARGET | STATE_SENT_CMD | 5595 STATE_GOT_STATUS | STATE_ARQ_DONE | 5596 STATE_XFERRED_DATA; 5597 } 5598 target->sft_alive = TRUE; 5599 } 5600 5601 /* 5602 * The firmware returns the number of bytes actually 5603 * xfered into/out of host. Compare this with what 5604 * we asked and if it is different, we lost frames ? 5605 */ 5606 if ((pkt->pkt_reason == 0) && (pkt->pkt_resid == 0) && 5607 (good_scsi_status) && 5608 (pkt->pkt_state & STATE_XFERRED_DATA) && 5609 (!(cmd->cmd_flags & CFLAG_CMDIOPB)) && 5610 (target->sft_device_type != DTYPE_ESI)) { 5611 int byte_cnt = 5612 fpkt->fcal_socal_request. 5613 sr_soc_hdr.sh_byte_cnt; 5614 if (cmd->cmd_flags & CFLAG_DMASEND) { 5615 if (byte_cnt != 0) { 5616 sf_log(sf, CE_NOTE, 5617 "!sf_cmd_callback: Lost Frame: " 5618 "(write) received 0x%x expected" 5619 " 0x%x target 0x%x\n", 5620 byte_cnt, cmd->cmd_dmacount, 5621 sf_alpa_to_switch[ 5622 target->sft_al_pa]); 5623 pkt->pkt_reason = CMD_INCOMPLETE; 5624 pkt->pkt_statistics |= STAT_ABORTED; 5625 } 5626 } else if (byte_cnt < cmd->cmd_dmacount) { 5627 sf_log(sf, CE_NOTE, 5628 "!sf_cmd_callback: " 5629 "Lost Frame: (read) " 5630 "received 0x%x expected 0x%x " 5631 "target 0x%x\n", byte_cnt, 5632 cmd->cmd_dmacount, 5633 sf_alpa_to_switch[ 5634 target->sft_al_pa]); 5635 pkt->pkt_reason = CMD_INCOMPLETE; 5636 pkt->pkt_statistics |= STAT_ABORTED; 5637 } 5638 } 5639 } 5640 5641 } else { 5642 5643 /* pkt status was not ok */ 5644 5645 switch (fpkt->fcal_pkt_status) { 5646 5647 case FCAL_STATUS_ERR_OFFLINE: 5648 SF_DMSG1("Fibre Channel Offline"); 5649 mutex_enter(&target->sft_mutex); 5650 if (!(target->sft_state & SF_TARGET_OFFLINE)) { 5651 target->sft_state |= (SF_TARGET_BUSY 5652 | SF_TARGET_MARK); 5653 } 5654 mutex_exit(&target->sft_mutex); 5655 (void) ndi_event_retrieve_cookie(sf->sf_event_hdl, 5656 target->sft_dip, FCAL_REMOVE_EVENT, 5657 &sf_remove_eid, NDI_EVENT_NOPASS); 5658 (void) ndi_event_run_callbacks(sf->sf_event_hdl, 5659 target->sft_dip, sf_remove_eid, NULL); 5660 pkt->pkt_reason = CMD_TRAN_ERR; 5661 pkt->pkt_statistics |= STAT_BUS_RESET; 5662 break; 5663 5664 case FCAL_STATUS_MAX_XCHG_EXCEEDED: 5665 sf_throttle(sf); 5666 sf->sf_use_lock = TRUE; 5667 pkt->pkt_reason = CMD_TRAN_ERR; 5668 pkt->pkt_state = STATE_GOT_BUS; 5669 pkt->pkt_statistics |= STAT_ABORTED; 5670 break; 5671 5672 case FCAL_STATUS_TIMEOUT: 5673 SF_DMSG1("Fibre Channel Timeout"); 5674 pkt->pkt_reason = CMD_TIMEOUT; 5675 break; 5676 5677 case FCAL_STATUS_ERR_OVERRUN: 5678 SF_DMSG1("CMD_DATA_OVR"); 5679 pkt->pkt_reason = CMD_DATA_OVR; 5680 break; 5681 5682 case FCAL_STATUS_UNKNOWN_CQ_TYPE: 5683 SF_DMSG1("Unknown CQ type"); 5684 pkt->pkt_reason = CMD_TRAN_ERR; 5685 break; 5686 5687 case FCAL_STATUS_BAD_SEG_CNT: 5688 SF_DMSG1("Bad SEG CNT"); 5689 pkt->pkt_reason = CMD_TRAN_ERR; 5690 break; 5691 5692 case FCAL_STATUS_BAD_XID: 5693 SF_DMSG1("Fibre Channel Invalid X_ID"); 5694 pkt->pkt_reason = CMD_TRAN_ERR; 5695 break; 5696 5697 case FCAL_STATUS_XCHG_BUSY: 5698 SF_DMSG1("Fibre Channel Exchange Busy"); 5699 pkt->pkt_reason = CMD_TRAN_ERR; 5700 break; 5701 5702 case FCAL_STATUS_INSUFFICIENT_CQES: 5703 SF_DMSG1("Insufficient CQEs"); 5704 pkt->pkt_reason = CMD_TRAN_ERR; 5705 break; 5706 5707 case FCAL_STATUS_ALLOC_FAIL: 5708 SF_DMSG1("ALLOC FAIL"); 5709 pkt->pkt_reason = CMD_TRAN_ERR; 5710 break; 5711 5712 case FCAL_STATUS_BAD_SID: 5713 SF_DMSG1("Fibre Channel Invalid S_ID"); 5714 pkt->pkt_reason = CMD_TRAN_ERR; 5715 break; 5716 5717 case FCAL_STATUS_INCOMPLETE_DMA_ERR: 5718 if (sf_core && (sf_core & SF_CORE_INCOMPLETE_DMA)) { 5719 sf_token = (int *)(uintptr_t) 5720 fpkt->fcal_socal_request.\ 5721 sr_soc_hdr.sh_request_token; 5722 (void) soc_take_core(sf->sf_sochandle, 5723 sf->sf_socp); 5724 sf_core = 0; 5725 } 5726 msg2 = 5727 "INCOMPLETE DMA XFER due to bad SOC+ card, replace HBA"; 5728 pkt->pkt_reason = CMD_INCOMPLETE; 5729 pkt->pkt_state = STATE_GOT_BUS; 5730 pkt->pkt_statistics |= STAT_ABORTED; 5731 break; 5732 5733 case FCAL_STATUS_CRC_ERR: 5734 msg2 = "Fibre Channel CRC Error on frames"; 5735 pkt->pkt_reason = CMD_INCOMPLETE; 5736 pkt->pkt_state = STATE_GOT_BUS; 5737 pkt->pkt_statistics |= STAT_ABORTED; 5738 break; 5739 5740 case FCAL_STATUS_NO_SEQ_INIT: 5741 SF_DMSG1("Fibre Channel Seq Init Error"); 5742 pkt->pkt_reason = CMD_TRAN_ERR; 5743 break; 5744 5745 case FCAL_STATUS_OPEN_FAIL: 5746 pkt->pkt_reason = CMD_TRAN_ERR; 5747 SF_DMSG1("Fibre Channel Open Failure"); 5748 if ((target->sft_state & (SF_TARGET_BUSY | 5749 SF_TARGET_MARK | SF_TARGET_OFFLINE)) == 0) { 5750 sf_log(sf, CE_NOTE, 5751 "!Open failure to target 0x%x " 5752 "forcing LIP\n", 5753 sf_alpa_to_switch[target->sft_al_pa]); 5754 sf_force_lip(sf); 5755 } 5756 break; 5757 5758 5759 case FCAL_STATUS_ONLINE_TIMEOUT: 5760 SF_DMSG1("Fibre Channel Online Timeout"); 5761 pkt->pkt_reason = CMD_TRAN_ERR; 5762 break; 5763 5764 default: 5765 SF_DMSG1("Unknown FC Status"); 5766 pkt->pkt_reason = CMD_TRAN_ERR; 5767 break; 5768 } 5769 } 5770 5771 #ifdef DEBUG 5772 /* 5773 * msg1 will be non-NULL if we've detected some sort of error 5774 */ 5775 if (msg1 != NULL && sfdebug >= 4) { 5776 sf_log(sf, CE_WARN, 5777 "!Transport error on cmd=0x%p target=0x%x: %s\n", 5778 (void *)fpkt, pkt->pkt_address.a_target, msg1); 5779 } 5780 #endif 5781 5782 if (msg2 != NULL) { 5783 sf_log(sf, CE_WARN, "!Transport error on target=0x%x: %s\n", 5784 pkt->pkt_address.a_target, msg2); 5785 } 5786 5787 ncmds = fpkt->fcal_ncmds; 5788 ASSERT(ncmds >= 0); 5789 if (ncmds >= (sf->sf_throttle - SF_HI_CMD_DELTA)) { 5790 #ifdef DEBUG 5791 if (!sf->sf_use_lock) { 5792 SF_DEBUG(4, (sf, CE_NOTE, "use lock flag on\n")); 5793 } 5794 #endif 5795 sf->sf_use_lock = TRUE; 5796 } 5797 5798 mutex_enter(&sf->sf_cmd_mutex); 5799 sf->sf_ncmds = ncmds; 5800 sf_throttle_start(sf); 5801 mutex_exit(&sf->sf_cmd_mutex); 5802 5803 if (!msg1 && !msg2) 5804 SF_DEBUG(6, (sf, CE_NOTE, "Completing pkt 0x%p\n", 5805 (void *)pkt)); 5806 if (pkt->pkt_comp != NULL) { 5807 (*pkt->pkt_comp)(pkt); 5808 } 5809 } 5810 5811 #undef SF_DMSG1 5812 5813 5814 5815 /* 5816 * start throttling for this instance 5817 */ 5818 static void 5819 sf_throttle_start(struct sf *sf) 5820 { 5821 struct sf_pkt *cmd, *prev_cmd = NULL; 5822 struct scsi_pkt *pkt; 5823 struct sf_target *target; 5824 5825 5826 ASSERT(mutex_owned(&sf->sf_cmd_mutex)); 5827 5828 cmd = sf->sf_pkt_head; 5829 while ((cmd != NULL) && 5830 (sf->sf_state == SF_STATE_ONLINE) && 5831 (sf->sf_ncmds < sf->sf_throttle)) { 5832 5833 pkt = CMD2PKT(cmd); 5834 5835 target = ADDR2TARGET(&pkt->pkt_address); 5836 if (target->sft_state & SF_TARGET_BUSY) { 5837 /* this command is busy -- go to next */ 5838 ASSERT(cmd->cmd_state != SF_STATE_ISSUED); 5839 prev_cmd = cmd; 5840 cmd = cmd->cmd_next; 5841 continue; 5842 } 5843 5844 ASSERT(cmd->cmd_state != SF_STATE_ISSUED); 5845 5846 /* this cmd not busy and not issued */ 5847 5848 /* remove this packet from the queue */ 5849 if (sf->sf_pkt_head == cmd) { 5850 /* this was the first packet */ 5851 sf->sf_pkt_head = cmd->cmd_next; 5852 } else if (sf->sf_pkt_tail == cmd) { 5853 /* this was the last packet */ 5854 sf->sf_pkt_tail = prev_cmd; 5855 if (prev_cmd != NULL) { 5856 prev_cmd->cmd_next = NULL; 5857 } 5858 } else { 5859 /* some packet in the middle of the queue */ 5860 ASSERT(prev_cmd != NULL); 5861 prev_cmd->cmd_next = cmd->cmd_next; 5862 } 5863 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 5864 5865 if (target->sft_state & SF_TARGET_OFFLINE) { 5866 mutex_exit(&sf->sf_cmd_mutex); 5867 pkt->pkt_reason = CMD_TRAN_ERR; 5868 if (pkt->pkt_comp != NULL) { 5869 (*pkt->pkt_comp)(cmd->cmd_pkt); 5870 } 5871 } else { 5872 sf_fill_ids(sf, cmd, target); 5873 if (sf_start_internal(sf, cmd) != TRAN_ACCEPT) { 5874 pkt->pkt_reason = CMD_TRAN_ERR; 5875 if (pkt->pkt_comp != NULL) { 5876 (*pkt->pkt_comp)(cmd->cmd_pkt); 5877 } 5878 } 5879 } 5880 mutex_enter(&sf->sf_cmd_mutex); 5881 cmd = sf->sf_pkt_head; 5882 prev_cmd = NULL; 5883 } 5884 } 5885 5886 5887 /* 5888 * called when the max exchange value is exceeded to throttle back commands 5889 */ 5890 static void 5891 sf_throttle(struct sf *sf) 5892 { 5893 int cmdmax = sf->sf_sochandle->fcal_cmdmax; 5894 5895 5896 mutex_enter(&sf->sf_cmd_mutex); 5897 5898 sf->sf_flag = TRUE; 5899 5900 if (sf->sf_ncmds > (cmdmax / 2)) { 5901 sf->sf_throttle = cmdmax / 2; 5902 } else { 5903 if (sf->sf_ncmds > SF_DECR_DELTA) { 5904 sf->sf_throttle = sf->sf_ncmds - SF_DECR_DELTA; 5905 } else { 5906 /* 5907 * This case is just a safeguard, should not really 5908 * happen(ncmds < SF_DECR_DELTA and MAX_EXCHG exceed 5909 */ 5910 sf->sf_throttle = SF_DECR_DELTA; 5911 } 5912 } 5913 mutex_exit(&sf->sf_cmd_mutex); 5914 5915 sf = sf->sf_sibling; 5916 if (sf != NULL) { 5917 mutex_enter(&sf->sf_cmd_mutex); 5918 sf->sf_flag = TRUE; 5919 if (sf->sf_ncmds >= (cmdmax / 2)) { 5920 sf->sf_throttle = cmdmax / 2; 5921 } else { 5922 if (sf->sf_ncmds > SF_DECR_DELTA) { 5923 sf->sf_throttle = sf->sf_ncmds - SF_DECR_DELTA; 5924 } else { 5925 sf->sf_throttle = SF_DECR_DELTA; 5926 } 5927 } 5928 5929 mutex_exit(&sf->sf_cmd_mutex); 5930 } 5931 } 5932 5933 5934 /* 5935 * sf watchdog routine, called for a timeout 5936 */ 5937 /*ARGSUSED*/ 5938 static void 5939 sf_watch(void *arg) 5940 { 5941 struct sf *sf; 5942 struct sf_els_hdr *privp; 5943 static int count = 0, pscan_count = 0; 5944 int cmdmax, i, mescount = 0; 5945 struct sf_target *target; 5946 5947 5948 sf_watchdog_time += sf_watchdog_timeout; 5949 count++; 5950 pscan_count++; 5951 5952 mutex_enter(&sf_global_mutex); 5953 sf_watch_running = 1; 5954 for (sf = sf_head; sf != NULL; sf = sf->sf_next) { 5955 5956 mutex_exit(&sf_global_mutex); 5957 5958 /* disable throttling while we're suspended */ 5959 mutex_enter(&sf->sf_mutex); 5960 if (sf->sf_state & SF_STATE_SUSPENDED) { 5961 mutex_exit(&sf->sf_mutex); 5962 SF_DEBUG(1, (sf, CE_CONT, 5963 "sf_watch, sf%d:throttle disabled " 5964 "due to DDI_SUSPEND\n", 5965 ddi_get_instance(sf->sf_dip))); 5966 mutex_enter(&sf_global_mutex); 5967 continue; 5968 } 5969 mutex_exit(&sf->sf_mutex); 5970 5971 cmdmax = sf->sf_sochandle->fcal_cmdmax; 5972 5973 if (sf->sf_take_core) { 5974 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp); 5975 } 5976 5977 mutex_enter(&sf->sf_cmd_mutex); 5978 5979 if (!sf->sf_flag) { 5980 if (sf->sf_throttle < (cmdmax / 2)) { 5981 sf->sf_throttle = cmdmax / 2; 5982 } else if ((sf->sf_throttle += SF_INCR_DELTA) > 5983 cmdmax) { 5984 sf->sf_throttle = cmdmax; 5985 } 5986 } else { 5987 sf->sf_flag = FALSE; 5988 } 5989 5990 sf->sf_ncmds_exp_avg = (sf->sf_ncmds + sf->sf_ncmds_exp_avg) 5991 >> 2; 5992 if ((sf->sf_ncmds <= (sf->sf_throttle - SF_LO_CMD_DELTA)) && 5993 (sf->sf_pkt_head == NULL)) { 5994 #ifdef DEBUG 5995 if (sf->sf_use_lock) { 5996 SF_DEBUG(4, (sf, CE_NOTE, 5997 "use lock flag off\n")); 5998 } 5999 #endif 6000 sf->sf_use_lock = FALSE; 6001 } 6002 6003 if (sf->sf_state == SF_STATE_ONLINE && sf->sf_pkt_head && 6004 sf->sf_ncmds < sf->sf_throttle) { 6005 sf_throttle_start(sf); 6006 } 6007 6008 mutex_exit(&sf->sf_cmd_mutex); 6009 6010 if (pscan_count >= sf_pool_scan_cnt) { 6011 if (sf->sf_ncmds_exp_avg < (sf->sf_cr_pool_cnt << 6012 SF_LOG2_ELEMS_IN_POOL) - SF_FREE_CR_EPSILON) { 6013 sf_crpool_free(sf); 6014 } 6015 } 6016 mutex_enter(&sf->sf_mutex); 6017 6018 privp = sf->sf_els_list; 6019 while (privp != NULL) { 6020 if (privp->timeout < sf_watchdog_time) { 6021 /* timeout this command */ 6022 privp = sf_els_timeout(sf, privp); 6023 } else if ((privp->timeout == SF_INVALID_TIMEOUT) && 6024 (privp->lip_cnt != sf->sf_lip_cnt)) { 6025 if (privp->prev != NULL) { 6026 privp->prev->next = privp->next; 6027 } 6028 if (sf->sf_els_list == privp) { 6029 sf->sf_els_list = privp->next; 6030 } 6031 if (privp->next != NULL) { 6032 privp->next->prev = privp->prev; 6033 } 6034 mutex_exit(&sf->sf_mutex); 6035 sf_els_free(privp->fpkt); 6036 mutex_enter(&sf->sf_mutex); 6037 privp = sf->sf_els_list; 6038 } else { 6039 privp = privp->next; 6040 } 6041 } 6042 6043 if (sf->sf_online_timer && sf->sf_online_timer < 6044 sf_watchdog_time) { 6045 for (i = 0; i < sf_max_targets; i++) { 6046 target = sf->sf_targets[i]; 6047 if (target != NULL) { 6048 if (!mescount && target->sft_state & 6049 SF_TARGET_BUSY) { 6050 sf_log(sf, CE_WARN, "!Loop " 6051 "Unstable: Failed to bring " 6052 "Loop Online\n"); 6053 mescount = 1; 6054 } 6055 target->sft_state |= SF_TARGET_MARK; 6056 } 6057 } 6058 sf_finish_init(sf, sf->sf_lip_cnt); 6059 sf->sf_state = SF_STATE_INIT; 6060 sf->sf_online_timer = 0; 6061 } 6062 6063 if (sf->sf_state == SF_STATE_ONLINE) { 6064 mutex_exit(&sf->sf_mutex); 6065 if (count >= sf_pkt_scan_cnt) { 6066 sf_check_targets(sf); 6067 } 6068 } else if ((sf->sf_state == SF_STATE_OFFLINE) && 6069 (sf->sf_timer < sf_watchdog_time)) { 6070 for (i = 0; i < sf_max_targets; i++) { 6071 target = sf->sf_targets[i]; 6072 if ((target != NULL) && 6073 (target->sft_state & 6074 SF_TARGET_BUSY)) { 6075 sf_log(sf, CE_WARN, 6076 "!Offline Timeout\n"); 6077 if (sf_core && (sf_core & 6078 SF_CORE_OFFLINE_TIMEOUT)) { 6079 (void) soc_take_core( 6080 sf->sf_sochandle, 6081 sf->sf_socp); 6082 sf_core = 0; 6083 } 6084 break; 6085 } 6086 } 6087 sf_finish_init(sf, sf->sf_lip_cnt); 6088 sf->sf_state = SF_STATE_INIT; 6089 mutex_exit(&sf->sf_mutex); 6090 } else { 6091 mutex_exit(&sf->sf_mutex); 6092 } 6093 mutex_enter(&sf_global_mutex); 6094 } 6095 mutex_exit(&sf_global_mutex); 6096 if (count >= sf_pkt_scan_cnt) { 6097 count = 0; 6098 } 6099 if (pscan_count >= sf_pool_scan_cnt) { 6100 pscan_count = 0; 6101 } 6102 6103 /* reset timeout */ 6104 sf_watchdog_id = timeout(sf_watch, (caddr_t)0, sf_watchdog_tick); 6105 6106 /* signal waiting thread */ 6107 mutex_enter(&sf_global_mutex); 6108 sf_watch_running = 0; 6109 cv_broadcast(&sf_watch_cv); 6110 mutex_exit(&sf_global_mutex); 6111 } 6112 6113 6114 /* 6115 * called during a timeout to check targets 6116 */ 6117 static void 6118 sf_check_targets(struct sf *sf) 6119 { 6120 struct sf_target *target; 6121 int i; 6122 struct sf_pkt *cmd; 6123 struct scsi_pkt *pkt; 6124 int lip_cnt; 6125 6126 mutex_enter(&sf->sf_mutex); 6127 lip_cnt = sf->sf_lip_cnt; 6128 mutex_exit(&sf->sf_mutex); 6129 6130 /* check scan all possible targets */ 6131 for (i = 0; i < sf_max_targets; i++) { 6132 target = sf->sf_targets[i]; 6133 while (target != NULL) { 6134 mutex_enter(&target->sft_pkt_mutex); 6135 if (target->sft_alive && target->sft_scan_count != 6136 sf_target_scan_cnt) { 6137 target->sft_alive = 0; 6138 target->sft_scan_count++; 6139 mutex_exit(&target->sft_pkt_mutex); 6140 return; 6141 } 6142 target->sft_alive = 0; 6143 target->sft_scan_count = 0; 6144 cmd = target->sft_pkt_head; 6145 while (cmd != (struct sf_pkt *)&target->sft_pkt_head) { 6146 mutex_enter(&cmd->cmd_abort_mutex); 6147 if (cmd->cmd_state == SF_STATE_ISSUED && 6148 ((cmd->cmd_timeout && sf_watchdog_time > 6149 #ifdef DEBUG 6150 cmd->cmd_timeout) || sf_abort_flag)) { 6151 sf_abort_flag = 0; 6152 #else 6153 cmd->cmd_timeout))) { 6154 #endif 6155 cmd->cmd_timeout = 0; 6156 /* prevent reset from getting at this packet */ 6157 cmd->cmd_state = SF_STATE_ABORTING; 6158 mutex_exit(&cmd->cmd_abort_mutex); 6159 mutex_exit(&target->sft_pkt_mutex); 6160 sf->sf_stats.tstats[i].timeouts++; 6161 if (sf_target_timeout(sf, cmd)) 6162 return; 6163 else { 6164 if (lip_cnt != sf->sf_lip_cnt) { 6165 return; 6166 } else { 6167 mutex_enter(&target-> 6168 sft_pkt_mutex); 6169 cmd = target-> 6170 sft_pkt_head; 6171 } 6172 } 6173 /* 6174 * if the abort and lip fail, a reset will be carried out. 6175 * But the reset will ignore this packet. We have waited at least 6176 * 20 seconds after the initial timeout. Now, complete it here. 6177 * This also takes care of spurious bad aborts. 6178 */ 6179 } else if ((cmd->cmd_state == 6180 SF_STATE_ABORTING) && (cmd->cmd_timeout 6181 <= sf_watchdog_time)) { 6182 cmd->cmd_state = SF_STATE_IDLE; 6183 mutex_exit(&cmd->cmd_abort_mutex); 6184 mutex_exit(&target->sft_pkt_mutex); 6185 SF_DEBUG(1, (sf, CE_NOTE, 6186 "Command 0x%p to sft 0x%p" 6187 " delayed release\n", 6188 (void *)cmd, (void *)target)); 6189 pkt = cmd->cmd_pkt; 6190 pkt->pkt_statistics |= 6191 (STAT_TIMEOUT|STAT_ABORTED); 6192 pkt->pkt_reason = CMD_TIMEOUT; 6193 if (pkt->pkt_comp) { 6194 scsi_hba_pkt_comp(pkt); 6195 /* handle deferred_destroy case */ 6196 } else { 6197 if ((cmd->cmd_block->fcp_cntl. 6198 cntl_reset == 1) || 6199 (cmd->cmd_block-> 6200 fcp_cntl.cntl_abort_tsk == 6201 1)) { 6202 cmd->cmd_block-> 6203 fcp_cntl. 6204 cntl_reset = 0; 6205 cmd->cmd_block-> 6206 fcp_cntl. 6207 cntl_abort_tsk = 0; 6208 cmd->cmd_fp_pkt-> 6209 fcal_pkt_comp = 6210 sf_cmd_callback; 6211 /* for cache */ 6212 sf_scsi_destroy_pkt 6213 (&pkt->pkt_address, 6214 pkt); 6215 } 6216 } 6217 mutex_enter(&target->sft_pkt_mutex); 6218 cmd = target->sft_pkt_head; 6219 } else { 6220 mutex_exit(&cmd->cmd_abort_mutex); 6221 cmd = cmd->cmd_forw; 6222 } 6223 } 6224 mutex_exit(&target->sft_pkt_mutex); 6225 target = target->sft_next_lun; 6226 } 6227 } 6228 } 6229 6230 6231 /* 6232 * a command to a target has timed out 6233 * return TRUE iff cmd abort failed or timed out, else return FALSE 6234 */ 6235 static int 6236 sf_target_timeout(struct sf *sf, struct sf_pkt *cmd) 6237 { 6238 int rval; 6239 struct scsi_pkt *pkt; 6240 struct fcal_packet *fpkt; 6241 int tgt_id; 6242 int retval = FALSE; 6243 6244 6245 SF_DEBUG(1, (sf, CE_NOTE, "Command 0x%p to target %x timed out\n", 6246 (void *)cmd->cmd_fp_pkt, cmd->cmd_pkt->pkt_address.a_target)); 6247 6248 fpkt = cmd->cmd_fp_pkt; 6249 6250 if (sf_core && (sf_core & SF_CORE_CMD_TIMEOUT)) { 6251 sf_token = (int *)(uintptr_t) 6252 fpkt->fcal_socal_request.sr_soc_hdr.\ 6253 sh_request_token; 6254 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp); 6255 sf_core = 0; 6256 } 6257 6258 /* call the transport to abort a command */ 6259 rval = soc_abort(sf->sf_sochandle, sf->sf_socp, 6260 sf->sf_sochandle->fcal_portno, fpkt, 1); 6261 6262 switch (rval) { 6263 case FCAL_ABORTED: 6264 SF_DEBUG(1, (sf, CE_NOTE, "Command Abort succeeded\n")); 6265 pkt = cmd->cmd_pkt; 6266 cmd->cmd_state = SF_STATE_IDLE; 6267 pkt->pkt_statistics |= (STAT_TIMEOUT|STAT_ABORTED); 6268 pkt->pkt_reason = CMD_TIMEOUT; 6269 if (pkt->pkt_comp != NULL) { 6270 (*pkt->pkt_comp)(pkt); 6271 } 6272 break; /* success */ 6273 6274 case FCAL_ABORT_FAILED: 6275 SF_DEBUG(1, (sf, CE_NOTE, "Command Abort failed at target\n")); 6276 pkt = cmd->cmd_pkt; 6277 cmd->cmd_state = SF_STATE_IDLE; 6278 pkt->pkt_reason = CMD_TIMEOUT; 6279 pkt->pkt_statistics |= STAT_TIMEOUT; 6280 tgt_id = pkt->pkt_address.a_target; 6281 sf->sf_stats.tstats[tgt_id].abts_failures++; 6282 if (pkt->pkt_comp != NULL) { 6283 (*pkt->pkt_comp)(pkt); 6284 } 6285 break; 6286 6287 case FCAL_BAD_ABORT: 6288 if (sf_core && (sf_core & SF_CORE_BAD_ABORT)) { 6289 sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\ 6290 sr_soc_hdr.sh_request_token; 6291 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp); 6292 sf_core = 0; 6293 } 6294 SF_DEBUG(1, (sf, CE_NOTE, "Command Abort bad abort\n")); 6295 cmd->cmd_timeout = sf_watchdog_time + cmd->cmd_pkt->pkt_time 6296 + 20; 6297 break; 6298 6299 case FCAL_TIMEOUT: 6300 retval = TRUE; 6301 break; 6302 6303 default: 6304 pkt = cmd->cmd_pkt; 6305 tgt_id = pkt->pkt_address.a_target; 6306 sf_log(sf, CE_WARN, 6307 "Command Abort failed target 0x%x, forcing a LIP\n", tgt_id); 6308 if (sf_core && (sf_core & SF_CORE_ABORT_TIMEOUT)) { 6309 sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\ 6310 sr_soc_hdr.sh_request_token; 6311 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp); 6312 sf_core = 0; 6313 } 6314 sf_force_lip(sf); 6315 retval = TRUE; 6316 break; 6317 } 6318 6319 return (retval); 6320 } 6321 6322 6323 /* 6324 * an ELS command has timed out 6325 * return ??? 6326 */ 6327 static struct sf_els_hdr * 6328 sf_els_timeout(struct sf *sf, struct sf_els_hdr *privp) 6329 { 6330 struct fcal_packet *fpkt; 6331 int rval, dflag, timeout = SF_ELS_TIMEOUT; 6332 uint_t lip_cnt = privp->lip_cnt; 6333 uchar_t els_code = privp->els_code; 6334 struct sf_target *target = privp->target; 6335 char what[64]; 6336 6337 fpkt = privp->fpkt; 6338 dflag = privp->delayed_retry; 6339 /* use as temporary state variable */ 6340 privp->timeout = SF_INVALID_TIMEOUT; 6341 mutex_exit(&sf->sf_mutex); 6342 6343 if (privp->fpkt->fcal_pkt_comp == sf_els_callback) { 6344 /* 6345 * take socal core if required. Timeouts for IB and hosts 6346 * are not very interesting, so we take socal core only 6347 * if the timeout is *not* for a IB or host. 6348 */ 6349 if (sf_core && (sf_core & SF_CORE_ELS_TIMEOUT) && 6350 ((sf_alpa_to_switch[privp->dest_nport_id] & 6351 0x0d) != 0x0d) && ((privp->dest_nport_id != 1) || 6352 (privp->dest_nport_id != 2) || 6353 (privp->dest_nport_id != 4) || 6354 (privp->dest_nport_id != 8) || 6355 (privp->dest_nport_id != 0xf))) { 6356 sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\ 6357 sr_soc_hdr.sh_request_token; 6358 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp); 6359 sf_core = 0; 6360 } 6361 (void) sprintf(what, "ELS 0x%x", privp->els_code); 6362 } else if (privp->fpkt->fcal_pkt_comp == sf_reportlun_callback) { 6363 if (sf_core && (sf_core & SF_CORE_REPORTLUN_TIMEOUT)) { 6364 sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\ 6365 sr_soc_hdr.sh_request_token; 6366 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp); 6367 sf_core = 0; 6368 } 6369 timeout = SF_FCP_TIMEOUT; 6370 (void) sprintf(what, "REPORT_LUNS"); 6371 } else if (privp->fpkt->fcal_pkt_comp == sf_inq_callback) { 6372 if (sf_core && (sf_core & SF_CORE_INQUIRY_TIMEOUT)) { 6373 sf_token = (int *)(uintptr_t) 6374 fpkt->fcal_socal_request.\ 6375 sr_soc_hdr.sh_request_token; 6376 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp); 6377 sf_core = 0; 6378 } 6379 timeout = SF_FCP_TIMEOUT; 6380 (void) sprintf(what, "INQUIRY to LUN 0x%lx", 6381 (long)SCSA_LUN(target)); 6382 } else { 6383 (void) sprintf(what, "UNKNOWN OPERATION"); 6384 } 6385 6386 if (dflag) { 6387 /* delayed retry */ 6388 SF_DEBUG(2, (sf, CE_CONT, 6389 "!sf%d: %s to target %x delayed retry\n", 6390 ddi_get_instance(sf->sf_dip), what, 6391 sf_alpa_to_switch[privp->dest_nport_id])); 6392 privp->delayed_retry = FALSE; 6393 goto try_again; 6394 } 6395 6396 sf_log(sf, CE_NOTE, "!%s to target 0x%x alpa 0x%x timed out\n", 6397 what, sf_alpa_to_switch[privp->dest_nport_id], 6398 privp->dest_nport_id); 6399 6400 rval = soc_abort(sf->sf_sochandle, sf->sf_socp, sf->sf_sochandle 6401 ->fcal_portno, fpkt, 1); 6402 if (rval == FCAL_ABORTED || rval == FCAL_ABORT_FAILED) { 6403 SF_DEBUG(1, (sf, CE_NOTE, "!%s abort to al_pa %x succeeded\n", 6404 what, privp->dest_nport_id)); 6405 try_again: 6406 6407 mutex_enter(&sf->sf_mutex); 6408 if (privp->prev != NULL) { 6409 privp->prev->next = privp->next; 6410 } 6411 if (sf->sf_els_list == privp) { 6412 sf->sf_els_list = privp->next; 6413 } 6414 if (privp->next != NULL) { 6415 privp->next->prev = privp->prev; 6416 } 6417 privp->prev = privp->next = NULL; 6418 if (lip_cnt == sf->sf_lip_cnt) { 6419 privp->timeout = sf_watchdog_time + timeout; 6420 if ((++(privp->retries) < sf_els_retries) || 6421 (dflag && (privp->retries < SF_BSY_RETRIES))) { 6422 mutex_exit(&sf->sf_mutex); 6423 sf_log(sf, CE_NOTE, 6424 "!%s to target 0x%x retrying\n", 6425 what, 6426 sf_alpa_to_switch[privp->dest_nport_id]); 6427 if (sf_els_transport(sf, privp) == 1) { 6428 mutex_enter(&sf->sf_mutex); 6429 return (sf->sf_els_list); /* success */ 6430 } 6431 mutex_enter(&sf->sf_mutex); 6432 fpkt = NULL; 6433 } 6434 if ((lip_cnt == sf->sf_lip_cnt) && 6435 (els_code != LA_ELS_LOGO)) { 6436 if (target != NULL) { 6437 sf_offline_target(sf, target); 6438 } 6439 if (sf->sf_lip_cnt == lip_cnt) { 6440 sf->sf_device_count--; 6441 ASSERT(sf->sf_device_count >= 0); 6442 if (sf->sf_device_count == 0) { 6443 sf_finish_init(sf, 6444 sf->sf_lip_cnt); 6445 } 6446 } 6447 } 6448 privp = sf->sf_els_list; 6449 mutex_exit(&sf->sf_mutex); 6450 if (fpkt != NULL) { 6451 sf_els_free(fpkt); 6452 } 6453 } else { 6454 mutex_exit(&sf->sf_mutex); 6455 sf_els_free(privp->fpkt); 6456 privp = NULL; 6457 } 6458 } else { 6459 if (sf_core && (sf_core & SF_CORE_ELS_FAILED)) { 6460 sf_token = (int *)(uintptr_t) 6461 fpkt->fcal_socal_request.\ 6462 sr_soc_hdr.sh_request_token; 6463 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp); 6464 sf_core = 0; 6465 } 6466 sf_log(sf, CE_NOTE, "%s abort to target 0x%x failed. " 6467 "status=0x%x, forcing LIP\n", what, 6468 sf_alpa_to_switch[privp->dest_nport_id], rval); 6469 privp = NULL; 6470 if (sf->sf_lip_cnt == lip_cnt) { 6471 sf_force_lip(sf); 6472 } 6473 } 6474 6475 mutex_enter(&sf->sf_mutex); 6476 return (privp); 6477 } 6478 6479 6480 /* 6481 * called by timeout when a reset times out 6482 */ 6483 /*ARGSUSED*/ 6484 static void 6485 sf_check_reset_delay(void *arg) 6486 { 6487 struct sf *sf; 6488 struct sf_target *target; 6489 struct sf_reset_list *rp, *tp; 6490 uint_t lip_cnt, reset_timeout_flag = FALSE; 6491 clock_t lb; 6492 6493 lb = ddi_get_lbolt(); 6494 6495 mutex_enter(&sf_global_mutex); 6496 6497 sf_reset_timeout_id = 0; 6498 6499 for (sf = sf_head; sf != NULL; sf = sf->sf_next) { 6500 6501 mutex_exit(&sf_global_mutex); 6502 mutex_enter(&sf->sf_mutex); 6503 6504 /* is this type cast needed? */ 6505 tp = (struct sf_reset_list *)&sf->sf_reset_list; 6506 6507 rp = sf->sf_reset_list; 6508 while (rp != NULL) { 6509 if (((rp->timeout - lb) < 0) && 6510 (rp->lip_cnt == sf->sf_lip_cnt)) { 6511 tp->next = rp->next; 6512 mutex_exit(&sf->sf_mutex); 6513 target = rp->target; 6514 lip_cnt = rp->lip_cnt; 6515 kmem_free(rp, sizeof (struct sf_reset_list)); 6516 /* abort all cmds for this target */ 6517 while (target) { 6518 sf_abort_all(sf, target, FALSE, 6519 lip_cnt, TRUE); 6520 mutex_enter(&target->sft_mutex); 6521 if (lip_cnt == sf->sf_lip_cnt) { 6522 target->sft_state &= 6523 ~SF_TARGET_BUSY; 6524 } 6525 mutex_exit(&target->sft_mutex); 6526 target = target->sft_next_lun; 6527 } 6528 mutex_enter(&sf->sf_mutex); 6529 tp = (struct sf_reset_list *) 6530 &sf->sf_reset_list; 6531 rp = sf->sf_reset_list; 6532 lb = ddi_get_lbolt(); 6533 } else if (rp->lip_cnt != sf->sf_lip_cnt) { 6534 tp->next = rp->next; 6535 kmem_free(rp, sizeof (struct sf_reset_list)); 6536 rp = tp->next; 6537 } else { 6538 reset_timeout_flag = TRUE; 6539 tp = rp; 6540 rp = rp->next; 6541 } 6542 } 6543 mutex_exit(&sf->sf_mutex); 6544 mutex_enter(&sf_global_mutex); 6545 } 6546 6547 if (reset_timeout_flag && (sf_reset_timeout_id == 0)) { 6548 sf_reset_timeout_id = timeout(sf_check_reset_delay, 6549 NULL, drv_usectohz(SF_TARGET_RESET_DELAY)); 6550 } 6551 6552 mutex_exit(&sf_global_mutex); 6553 } 6554 6555 6556 /* 6557 * called to "reset the bus", i.e. force loop initialization (and address 6558 * re-negotiation) 6559 */ 6560 static void 6561 sf_force_lip(struct sf *sf) 6562 { 6563 int i; 6564 struct sf_target *target; 6565 6566 6567 /* disable restart of lip if we're suspended */ 6568 mutex_enter(&sf->sf_mutex); 6569 if (sf->sf_state & SF_STATE_SUSPENDED) { 6570 mutex_exit(&sf->sf_mutex); 6571 SF_DEBUG(1, (sf, CE_CONT, 6572 "sf_force_lip, sf%d: lip restart disabled " 6573 "due to DDI_SUSPEND\n", 6574 ddi_get_instance(sf->sf_dip))); 6575 return; 6576 } 6577 6578 sf_log(sf, CE_NOTE, "Forcing lip\n"); 6579 6580 for (i = 0; i < sf_max_targets; i++) { 6581 target = sf->sf_targets[i]; 6582 while (target != NULL) { 6583 mutex_enter(&target->sft_mutex); 6584 if (!(target->sft_state & SF_TARGET_OFFLINE)) 6585 target->sft_state |= SF_TARGET_BUSY; 6586 mutex_exit(&target->sft_mutex); 6587 target = target->sft_next_lun; 6588 } 6589 } 6590 6591 sf->sf_lip_cnt++; 6592 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT; 6593 sf->sf_state = SF_STATE_OFFLINE; 6594 mutex_exit(&sf->sf_mutex); 6595 sf->sf_stats.lip_count++; /* no mutex for this? */ 6596 6597 #ifdef DEBUG 6598 /* are we allowing LIPs ?? */ 6599 if (sf_lip_flag != 0) { 6600 #endif 6601 /* call the transport to force loop initialization */ 6602 if (((i = soc_force_lip(sf->sf_sochandle, sf->sf_socp, 6603 sf->sf_sochandle->fcal_portno, 1, 6604 FCAL_FORCE_LIP)) != FCAL_SUCCESS) && 6605 (i != FCAL_TIMEOUT)) { 6606 /* force LIP failed */ 6607 if (sf_core && (sf_core & SF_CORE_LIP_FAILED)) { 6608 (void) soc_take_core(sf->sf_sochandle, 6609 sf->sf_socp); 6610 sf_core = 0; 6611 } 6612 #ifdef DEBUG 6613 /* are we allowing reset after LIP failed ?? */ 6614 if (sf_reset_flag != 0) { 6615 #endif 6616 /* restart socal after resetting it */ 6617 sf_log(sf, CE_NOTE, 6618 "!Force lip failed Status code 0x%x." 6619 " Reseting\n", i); 6620 /* call transport to force a reset */ 6621 soc_force_reset(sf->sf_sochandle, sf->sf_socp, 6622 sf->sf_sochandle->fcal_portno, 1); 6623 #ifdef DEBUG 6624 } 6625 #endif 6626 } 6627 #ifdef DEBUG 6628 } 6629 #endif 6630 } 6631 6632 6633 /* 6634 * called by the transport when an unsolicited ELS is received 6635 */ 6636 static void 6637 sf_unsol_els_callback(void *arg, soc_response_t *srp, caddr_t payload) 6638 { 6639 struct sf *sf = (struct sf *)arg; 6640 els_payload_t *els = (els_payload_t *)payload; 6641 struct la_els_rjt *rsp; 6642 int i, tgt_id; 6643 uchar_t dest_id; 6644 struct fcal_packet *fpkt; 6645 fc_frame_header_t *hp; 6646 struct sf_els_hdr *privp; 6647 6648 6649 if ((els == NULL) || ((i = srp->sr_soc_hdr.sh_byte_cnt) == 0)) { 6650 return; 6651 } 6652 6653 if (i > SOC_CQE_PAYLOAD) { 6654 i = SOC_CQE_PAYLOAD; 6655 } 6656 6657 dest_id = (uchar_t)srp->sr_fc_frame_hdr.s_id; 6658 tgt_id = sf_alpa_to_switch[dest_id]; 6659 6660 switch (els->els_cmd.c.ls_command) { 6661 6662 case LA_ELS_LOGO: 6663 /* 6664 * logout received -- log the fact 6665 */ 6666 sf->sf_stats.tstats[tgt_id].logouts_recvd++; 6667 sf_log(sf, CE_NOTE, "!LOGO recvd from target %x, %s\n", 6668 tgt_id, 6669 sf_lip_on_plogo ? "Forcing LIP...." : ""); 6670 if (sf_lip_on_plogo) { 6671 sf_force_lip(sf); 6672 } 6673 break; 6674 6675 default: /* includes LA_ELS_PLOGI */ 6676 /* 6677 * something besides a logout received -- we don't handle 6678 * this so send back a reject saying its unsupported 6679 */ 6680 6681 sf_log(sf, CE_NOTE, "!ELS 0x%x recvd from target 0x%x\n", 6682 els->els_cmd.c.ls_command, tgt_id); 6683 6684 6685 /* allocate room for a response */ 6686 if (sf_els_alloc(sf, dest_id, sizeof (struct sf_els_hdr), 6687 sizeof (struct la_els_rjt), sizeof (union sf_els_rsp), 6688 (caddr_t *)&privp, (caddr_t *)&rsp) == NULL) { 6689 break; 6690 } 6691 6692 fpkt = privp->fpkt; 6693 6694 /* fill in pkt header */ 6695 hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr; 6696 hp->r_ctl = R_CTL_ELS_RSP; 6697 hp->f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT; 6698 hp->ox_id = srp->sr_fc_frame_hdr.ox_id; 6699 hp->rx_id = srp->sr_fc_frame_hdr.rx_id; 6700 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = 6701 CQ_TYPE_OUTBOUND; 6702 6703 fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 1; 6704 6705 /* fill in response */ 6706 rsp->ls_code = LA_ELS_RJT; /* reject this ELS */ 6707 rsp->mbz[0] = 0; 6708 rsp->mbz[1] = 0; 6709 rsp->mbz[2] = 0; 6710 ((struct la_els_logi *)privp->rsp)->ls_code = LA_ELS_ACC; 6711 *((int *)&rsp->reserved) = 0; 6712 rsp->reason_code = RJT_UNSUPPORTED; 6713 privp->retries = sf_els_retries; 6714 privp->els_code = LA_ELS_RJT; 6715 privp->timeout = (unsigned)0xffffffff; 6716 (void) sf_els_transport(sf, privp); 6717 break; 6718 } 6719 } 6720 6721 6722 /* 6723 * Error logging, printing, and debug print routines 6724 */ 6725 6726 /*PRINTFLIKE3*/ 6727 static void 6728 sf_log(struct sf *sf, int level, const char *fmt, ...) 6729 { 6730 char buf[256]; 6731 dev_info_t *dip; 6732 va_list ap; 6733 6734 if (sf != NULL) { 6735 dip = sf->sf_dip; 6736 } else { 6737 dip = NULL; 6738 } 6739 6740 va_start(ap, fmt); 6741 (void) vsprintf(buf, fmt, ap); 6742 va_end(ap); 6743 scsi_log(dip, "sf", level, buf); 6744 } 6745 6746 6747 /* 6748 * called to get some sf kstats -- return 0 on success else return errno 6749 */ 6750 static int 6751 sf_kstat_update(kstat_t *ksp, int rw) 6752 { 6753 struct sf *sf; 6754 6755 if (rw == KSTAT_WRITE) { 6756 /* can't write */ 6757 return (EACCES); 6758 } 6759 6760 sf = ksp->ks_private; 6761 sf->sf_stats.ncmds = sf->sf_ncmds; 6762 sf->sf_stats.throttle_limit = sf->sf_throttle; 6763 sf->sf_stats.cr_pool_size = sf->sf_cr_pool_cnt; 6764 6765 return (0); /* success */ 6766 } 6767 6768 6769 /* 6770 * Unix Entry Points 6771 */ 6772 6773 /* 6774 * driver entry point for opens on control device 6775 */ 6776 /* ARGSUSED */ 6777 static int 6778 sf_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p) 6779 { 6780 dev_t dev = *dev_p; 6781 struct sf *sf; 6782 6783 6784 /* just ensure soft state exists for this device */ 6785 sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev))); 6786 if (sf == NULL) { 6787 return (ENXIO); 6788 } 6789 6790 ++(sf->sf_check_n_close); 6791 6792 return (0); 6793 } 6794 6795 6796 /* 6797 * driver entry point for last close on control device 6798 */ 6799 /* ARGSUSED */ 6800 static int 6801 sf_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 6802 { 6803 struct sf *sf; 6804 6805 sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev))); 6806 if (sf == NULL) { 6807 return (ENXIO); 6808 } 6809 6810 if (!sf->sf_check_n_close) { /* if this flag is zero */ 6811 cmn_err(CE_WARN, "sf%d: trying to close unopened instance", 6812 SF_MINOR2INST(getminor(dev))); 6813 return (ENODEV); 6814 } else { 6815 --(sf->sf_check_n_close); 6816 } 6817 return (0); 6818 } 6819 6820 6821 /* 6822 * driver entry point for sf ioctl commands 6823 */ 6824 /* ARGSUSED */ 6825 static int 6826 sf_ioctl(dev_t dev, 6827 int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p) 6828 { 6829 struct sf *sf; 6830 struct sf_target *target; 6831 uchar_t al_pa; 6832 struct sf_al_map map; 6833 int cnt, i; 6834 int retval; /* return value */ 6835 struct devctl_iocdata *dcp; 6836 dev_info_t *cdip; 6837 struct scsi_address ap; 6838 scsi_hba_tran_t *tran; 6839 6840 6841 sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev))); 6842 if (sf == NULL) { 6843 return (ENXIO); 6844 } 6845 6846 /* handle all ioctls */ 6847 switch (cmd) { 6848 6849 /* 6850 * We can use the generic implementation for these ioctls 6851 */ 6852 case DEVCTL_DEVICE_GETSTATE: 6853 case DEVCTL_DEVICE_ONLINE: 6854 case DEVCTL_DEVICE_OFFLINE: 6855 case DEVCTL_BUS_GETSTATE: 6856 return (ndi_devctl_ioctl(sf->sf_dip, cmd, arg, mode, 0)); 6857 6858 /* 6859 * return FC map 6860 */ 6861 case SFIOCGMAP: 6862 if ((sf->sf_lilp_map->lilp_magic != FCAL_LILP_MAGIC && 6863 sf->sf_lilp_map->lilp_magic != FCAL_BADLILP_MAGIC) || 6864 sf->sf_state != SF_STATE_ONLINE) { 6865 retval = ENOENT; 6866 goto dun; 6867 } 6868 mutex_enter(&sf->sf_mutex); 6869 if (sf->sf_lilp_map->lilp_magic == FCAL_BADLILP_MAGIC) { 6870 int i, j = 0; 6871 6872 /* Need to generate a fake lilp map */ 6873 for (i = 0; i < sf_max_targets; i++) { 6874 if (sf->sf_targets[i]) 6875 sf->sf_lilp_map->lilp_alpalist[j++] = 6876 sf->sf_targets[i]-> 6877 sft_hard_address; 6878 } 6879 sf->sf_lilp_map->lilp_length = (uchar_t)j; 6880 } 6881 cnt = sf->sf_lilp_map->lilp_length; 6882 map.sf_count = (short)cnt; 6883 bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn, 6884 (caddr_t)&map.sf_hba_addr.sf_node_wwn, 6885 sizeof (la_wwn_t)); 6886 bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn, 6887 (caddr_t)&map.sf_hba_addr.sf_port_wwn, 6888 sizeof (la_wwn_t)); 6889 map.sf_hba_addr.sf_al_pa = sf->sf_al_pa; 6890 map.sf_hba_addr.sf_hard_address = 0; 6891 map.sf_hba_addr.sf_inq_dtype = DTYPE_UNKNOWN; 6892 for (i = 0; i < cnt; i++) { 6893 al_pa = sf->sf_lilp_map->lilp_alpalist[i]; 6894 map.sf_addr_pair[i].sf_al_pa = al_pa; 6895 if (al_pa == sf->sf_al_pa) { 6896 (void) bcopy((caddr_t)&sf->sf_sochandle 6897 ->fcal_n_wwn, (caddr_t)&map. 6898 sf_addr_pair[i].sf_node_wwn, 6899 sizeof (la_wwn_t)); 6900 (void) bcopy((caddr_t)&sf->sf_sochandle 6901 ->fcal_p_wwn, (caddr_t)&map. 6902 sf_addr_pair[i].sf_port_wwn, 6903 sizeof (la_wwn_t)); 6904 map.sf_addr_pair[i].sf_hard_address = 6905 al_pa; 6906 map.sf_addr_pair[i].sf_inq_dtype = 6907 DTYPE_PROCESSOR; 6908 continue; 6909 } 6910 target = sf->sf_targets[sf_alpa_to_switch[ 6911 al_pa]]; 6912 if (target != NULL) { 6913 mutex_enter(&target->sft_mutex); 6914 if (!(target->sft_state & 6915 (SF_TARGET_OFFLINE | 6916 SF_TARGET_BUSY))) { 6917 bcopy((caddr_t)&target-> 6918 sft_node_wwn, 6919 (caddr_t)&map.sf_addr_pair 6920 [i].sf_node_wwn, 6921 sizeof (la_wwn_t)); 6922 bcopy((caddr_t)&target-> 6923 sft_port_wwn, 6924 (caddr_t)&map.sf_addr_pair 6925 [i].sf_port_wwn, 6926 sizeof (la_wwn_t)); 6927 map.sf_addr_pair[i]. 6928 sf_hard_address 6929 = target->sft_hard_address; 6930 map.sf_addr_pair[i]. 6931 sf_inq_dtype 6932 = target->sft_device_type; 6933 mutex_exit(&target->sft_mutex); 6934 continue; 6935 } 6936 mutex_exit(&target->sft_mutex); 6937 } 6938 bzero((caddr_t)&map.sf_addr_pair[i]. 6939 sf_node_wwn, sizeof (la_wwn_t)); 6940 bzero((caddr_t)&map.sf_addr_pair[i]. 6941 sf_port_wwn, sizeof (la_wwn_t)); 6942 map.sf_addr_pair[i].sf_inq_dtype = 6943 DTYPE_UNKNOWN; 6944 } 6945 mutex_exit(&sf->sf_mutex); 6946 if (ddi_copyout((caddr_t)&map, (caddr_t)arg, 6947 sizeof (struct sf_al_map), mode) != 0) { 6948 retval = EFAULT; 6949 goto dun; 6950 } 6951 break; 6952 6953 /* 6954 * handle device control ioctls 6955 */ 6956 case DEVCTL_DEVICE_RESET: 6957 if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) { 6958 retval = EFAULT; 6959 goto dun; 6960 } 6961 if ((ndi_dc_getname(dcp) == NULL) || 6962 (ndi_dc_getaddr(dcp) == NULL)) { 6963 ndi_dc_freehdl(dcp); 6964 retval = EINVAL; 6965 goto dun; 6966 } 6967 cdip = ndi_devi_find(sf->sf_dip, 6968 ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); 6969 ndi_dc_freehdl(dcp); 6970 6971 if (cdip == NULL) { 6972 retval = ENXIO; 6973 goto dun; 6974 } 6975 6976 if ((target = sf_get_target_from_dip(sf, cdip)) == NULL) { 6977 retval = ENXIO; 6978 goto dun; 6979 } 6980 mutex_enter(&target->sft_mutex); 6981 if (!(target->sft_state & SF_TARGET_INIT_DONE)) { 6982 mutex_exit(&target->sft_mutex); 6983 retval = ENXIO; 6984 goto dun; 6985 } 6986 6987 /* This is ugly */ 6988 tran = kmem_zalloc(scsi_hba_tran_size(), KM_SLEEP); 6989 bcopy(target->sft_tran, tran, scsi_hba_tran_size()); 6990 mutex_exit(&target->sft_mutex); 6991 ap.a_hba_tran = tran; 6992 ap.a_target = sf_alpa_to_switch[target->sft_al_pa]; 6993 if (sf_reset(&ap, RESET_TARGET) == FALSE) { 6994 retval = EIO; 6995 } else { 6996 retval = 0; 6997 } 6998 kmem_free(tran, scsi_hba_tran_size()); 6999 goto dun; 7000 7001 case DEVCTL_BUS_QUIESCE: 7002 case DEVCTL_BUS_UNQUIESCE: 7003 retval = ENOTSUP; 7004 goto dun; 7005 7006 case DEVCTL_BUS_RESET: 7007 case DEVCTL_BUS_RESETALL: 7008 sf_force_lip(sf); 7009 break; 7010 7011 default: 7012 retval = ENOTTY; 7013 goto dun; 7014 } 7015 7016 retval = 0; /* success */ 7017 7018 dun: 7019 return (retval); 7020 } 7021 7022 7023 /* 7024 * get the target given a DIP 7025 */ 7026 static struct sf_target * 7027 sf_get_target_from_dip(struct sf *sf, dev_info_t *dip) 7028 { 7029 int i; 7030 struct sf_target *target; 7031 7032 7033 /* scan each hash queue for the DIP in question */ 7034 for (i = 0; i < SF_NUM_HASH_QUEUES; i++) { 7035 target = sf->sf_wwn_lists[i]; 7036 while (target != NULL) { 7037 if (target->sft_dip == dip) { 7038 return (target); /* success: target found */ 7039 } 7040 target = target->sft_next; 7041 } 7042 } 7043 return (NULL); /* failure: target not found */ 7044 } 7045 7046 7047 /* 7048 * called by the transport to get an event cookie 7049 */ 7050 static int 7051 sf_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 7052 ddi_eventcookie_t *event_cookiep) 7053 { 7054 struct sf *sf; 7055 7056 sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip)); 7057 if (sf == NULL) { 7058 /* can't find instance for this device */ 7059 return (DDI_FAILURE); 7060 } 7061 7062 return (ndi_event_retrieve_cookie(sf->sf_event_hdl, rdip, name, 7063 event_cookiep, NDI_EVENT_NOPASS)); 7064 7065 } 7066 7067 7068 /* 7069 * called by the transport to add an event callback 7070 */ 7071 static int 7072 sf_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 7073 ddi_eventcookie_t eventid, void (*callback)(dev_info_t *dip, 7074 ddi_eventcookie_t event, void *arg, void *impl_data), void *arg, 7075 ddi_callback_id_t *cb_id) 7076 { 7077 struct sf *sf; 7078 7079 sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip)); 7080 if (sf == NULL) { 7081 /* can't find instance for this device */ 7082 return (DDI_FAILURE); 7083 } 7084 7085 return (ndi_event_add_callback(sf->sf_event_hdl, rdip, 7086 eventid, callback, arg, NDI_SLEEP, cb_id)); 7087 7088 } 7089 7090 7091 /* 7092 * called by the transport to remove an event callback 7093 */ 7094 static int 7095 sf_bus_remove_eventcall(dev_info_t *devi, ddi_callback_id_t cb_id) 7096 { 7097 struct sf *sf; 7098 7099 sf = ddi_get_soft_state(sf_state, ddi_get_instance(devi)); 7100 if (sf == NULL) { 7101 /* can't find instance for this device */ 7102 return (DDI_FAILURE); 7103 } 7104 7105 return (ndi_event_remove_callback(sf->sf_event_hdl, cb_id)); 7106 } 7107 7108 7109 /* 7110 * called by the transport to post an event 7111 */ 7112 static int 7113 sf_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 7114 ddi_eventcookie_t eventid, void *impldata) 7115 { 7116 ddi_eventcookie_t remove_cookie, cookie; 7117 7118 /* is this a remove event ?? */ 7119 struct sf *sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip)); 7120 remove_cookie = ndi_event_tag_to_cookie(sf->sf_event_hdl, 7121 SF_EVENT_TAG_REMOVE); 7122 7123 if (remove_cookie == eventid) { 7124 struct sf_target *target; 7125 7126 /* handle remove event */ 7127 7128 if (sf == NULL) { 7129 /* no sf instance for this device */ 7130 return (NDI_FAILURE); 7131 } 7132 7133 /* get the target for this event */ 7134 if ((target = sf_get_target_from_dip(sf, rdip)) != NULL) { 7135 /* 7136 * clear device info for this target and mark as 7137 * not done 7138 */ 7139 mutex_enter(&target->sft_mutex); 7140 target->sft_dip = NULL; 7141 target->sft_state &= ~SF_TARGET_INIT_DONE; 7142 mutex_exit(&target->sft_mutex); 7143 return (NDI_SUCCESS); /* event handled */ 7144 } 7145 7146 /* no target for this event */ 7147 return (NDI_FAILURE); 7148 } 7149 7150 /* an insertion event */ 7151 if (ndi_busop_get_eventcookie(dip, rdip, FCAL_INSERT_EVENT, &cookie) 7152 != NDI_SUCCESS) { 7153 return (NDI_FAILURE); 7154 } 7155 7156 return (ndi_post_event(dip, rdip, cookie, impldata)); 7157 } 7158 7159 7160 /* 7161 * the sf hotplug daemon, one thread per sf instance 7162 */ 7163 static void 7164 sf_hp_daemon(void *arg) 7165 { 7166 struct sf *sf = (struct sf *)arg; 7167 struct sf_hp_elem *elem; 7168 struct sf_target *target; 7169 int tgt_id; 7170 callb_cpr_t cprinfo; 7171 7172 CALLB_CPR_INIT(&cprinfo, &sf->sf_hp_daemon_mutex, 7173 callb_generic_cpr, "sf_hp_daemon"); 7174 7175 mutex_enter(&sf->sf_hp_daemon_mutex); 7176 7177 do { 7178 while (sf->sf_hp_elem_head != NULL) { 7179 7180 /* save ptr to head of list */ 7181 elem = sf->sf_hp_elem_head; 7182 7183 /* take element off of list */ 7184 if (sf->sf_hp_elem_head == sf->sf_hp_elem_tail) { 7185 /* element only one in list -- list now empty */ 7186 sf->sf_hp_elem_head = NULL; 7187 sf->sf_hp_elem_tail = NULL; 7188 } else { 7189 /* remove element from head of list */ 7190 sf->sf_hp_elem_head = sf->sf_hp_elem_head->next; 7191 } 7192 7193 mutex_exit(&sf->sf_hp_daemon_mutex); 7194 7195 switch (elem->what) { 7196 case SF_ONLINE: 7197 /* online this target */ 7198 target = elem->target; 7199 (void) ndi_devi_online(elem->dip, 0); 7200 (void) ndi_event_retrieve_cookie( 7201 sf->sf_event_hdl, 7202 target->sft_dip, FCAL_INSERT_EVENT, 7203 &sf_insert_eid, NDI_EVENT_NOPASS); 7204 (void) ndi_event_run_callbacks(sf->sf_event_hdl, 7205 target->sft_dip, sf_insert_eid, NULL); 7206 break; 7207 case SF_OFFLINE: 7208 /* offline this target */ 7209 target = elem->target; 7210 tgt_id = sf_alpa_to_switch[target->sft_al_pa]; 7211 /* don't do NDI_DEVI_REMOVE for now */ 7212 if (ndi_devi_offline(elem->dip, 0) != 7213 NDI_SUCCESS) { 7214 SF_DEBUG(1, (sf, CE_WARN, "target %x, " 7215 "device offline failed", tgt_id)); 7216 } else { 7217 SF_DEBUG(1, (sf, CE_NOTE, "target %x, " 7218 "device offline succeeded\n", 7219 tgt_id)); 7220 } 7221 break; 7222 } 7223 kmem_free(elem, sizeof (struct sf_hp_elem)); 7224 mutex_enter(&sf->sf_hp_daemon_mutex); 7225 } 7226 7227 /* if exit is not already signaled */ 7228 if (sf->sf_hp_exit == 0) { 7229 /* wait to be signaled by work or exit */ 7230 CALLB_CPR_SAFE_BEGIN(&cprinfo); 7231 cv_wait(&sf->sf_hp_daemon_cv, &sf->sf_hp_daemon_mutex); 7232 CALLB_CPR_SAFE_END(&cprinfo, &sf->sf_hp_daemon_mutex); 7233 } 7234 } while (sf->sf_hp_exit == 0); 7235 7236 /* sf_hp_daemon_mutex is dropped by CALLB_CPR_EXIT */ 7237 CALLB_CPR_EXIT(&cprinfo); 7238 thread_exit(); /* no more hotplug thread */ 7239 /* NOTREACHED */ 7240 } 7241