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