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 9 * http://www.opensource.org/licenses/cddl1.txt. 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 (c) 2004-2012 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #define DEF_ICFG 1 28 29 #include <emlxs.h> 30 #include <emlxs_version.h> 31 32 33 static char emlxs_copyright[] = EMLXS_COPYRIGHT; 34 char emlxs_revision[] = EMLXS_REVISION; 35 char emlxs_version[] = EMLXS_VERSION; 36 char emlxs_name[] = EMLXS_NAME; 37 char emlxs_label[] = EMLXS_LABEL; 38 39 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 40 EMLXS_MSG_DEF(EMLXS_SOLARIS_C); 41 42 #ifdef MENLO_SUPPORT 43 static int32_t emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp); 44 #endif /* MENLO_SUPPORT */ 45 46 static void emlxs_fca_attach(emlxs_hba_t *hba); 47 static void emlxs_fca_detach(emlxs_hba_t *hba); 48 static void emlxs_drv_banner(emlxs_hba_t *hba); 49 50 static int32_t emlxs_get_props(emlxs_hba_t *hba); 51 static int32_t emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp, 52 uint32_t *pkt_flags); 53 static int32_t emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp); 54 static int32_t emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp); 55 static int32_t emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp); 56 static int32_t emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp); 57 static int32_t emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp); 58 static int32_t emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp); 59 static int32_t emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp); 60 static uint32_t emlxs_add_instance(int32_t ddiinst); 61 static void emlxs_iodone(emlxs_buf_t *sbp); 62 static int emlxs_pm_lower_power(dev_info_t *dip); 63 static int emlxs_pm_raise_power(dev_info_t *dip); 64 static void emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag, 65 uint32_t failed); 66 static void emlxs_iodone_server(void *arg1, void *arg2, void *arg3); 67 static uint32_t emlxs_integrity_check(emlxs_hba_t *hba); 68 static uint32_t emlxs_test(emlxs_hba_t *hba, uint32_t test_code, 69 uint32_t args, uint32_t *arg); 70 71 #if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4) 72 static void emlxs_read_vport_prop(emlxs_hba_t *hba); 73 #endif /* EMLXS_MODREV3 && EMLXS_MODREV4 */ 74 75 static void emlxs_mode_init_masks(emlxs_hba_t *hba); 76 77 78 extern int 79 emlxs_msiid_to_chan(emlxs_hba_t *hba, int msi_id); 80 extern int 81 emlxs_select_msiid(emlxs_hba_t *hba); 82 extern void 83 emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba); 84 85 /* 86 * Driver Entry Routines. 87 */ 88 static int32_t emlxs_detach(dev_info_t *, ddi_detach_cmd_t); 89 static int32_t emlxs_attach(dev_info_t *, ddi_attach_cmd_t); 90 static int32_t emlxs_open(dev_t *, int32_t, int32_t, cred_t *); 91 static int32_t emlxs_close(dev_t, int32_t, int32_t, cred_t *); 92 static int32_t emlxs_ioctl(dev_t, int32_t, intptr_t, int32_t, 93 cred_t *, int32_t *); 94 static int32_t emlxs_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 95 96 97 /* 98 * FC_AL Transport Functions. 99 */ 100 static opaque_t emlxs_fca_bind_port(dev_info_t *, fc_fca_port_info_t *, 101 fc_fca_bind_info_t *); 102 static void emlxs_fca_unbind_port(opaque_t); 103 static void emlxs_initialize_pkt(emlxs_port_t *, emlxs_buf_t *); 104 static int32_t emlxs_fca_get_cap(opaque_t, char *, void *); 105 static int32_t emlxs_fca_set_cap(opaque_t, char *, void *); 106 static int32_t emlxs_fca_get_map(opaque_t, fc_lilpmap_t *); 107 static int32_t emlxs_fca_ub_alloc(opaque_t, uint64_t *, uint32_t, 108 uint32_t *, uint32_t); 109 static int32_t emlxs_fca_ub_free(opaque_t, uint32_t, uint64_t *); 110 111 static opaque_t emlxs_fca_get_device(opaque_t, fc_portid_t); 112 static int32_t emlxs_fca_notify(opaque_t, uint32_t); 113 static void emlxs_ub_els_reject(emlxs_port_t *, fc_unsol_buf_t *); 114 115 /* 116 * Driver Internal Functions. 117 */ 118 119 static void emlxs_poll(emlxs_port_t *, emlxs_buf_t *); 120 static int32_t emlxs_power(dev_info_t *, int32_t, int32_t); 121 #ifdef EMLXS_I386 122 #ifdef S11 123 static int32_t emlxs_quiesce(dev_info_t *); 124 #endif /* S11 */ 125 #endif /* EMLXS_I386 */ 126 static int32_t emlxs_hba_resume(dev_info_t *); 127 static int32_t emlxs_hba_suspend(dev_info_t *); 128 static int32_t emlxs_hba_detach(dev_info_t *); 129 static int32_t emlxs_hba_attach(dev_info_t *); 130 static void emlxs_lock_destroy(emlxs_hba_t *); 131 static void emlxs_lock_init(emlxs_hba_t *); 132 133 char *emlxs_pm_components[] = { 134 "NAME=" DRIVER_NAME "000", 135 "0=Device D3 State", 136 "1=Device D0 State" 137 }; 138 139 140 /* 141 * Default emlx dma limits 142 */ 143 ddi_dma_lim_t emlxs_dma_lim = { 144 (uint32_t)0, /* dlim_addr_lo */ 145 (uint32_t)0xffffffff, /* dlim_addr_hi */ 146 (uint_t)0x00ffffff, /* dlim_cntr_max */ 147 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dlim_burstsizes */ 148 1, /* dlim_minxfer */ 149 0x00ffffff /* dlim_dmaspeed */ 150 }; 151 152 /* 153 * Be careful when using these attributes; the defaults listed below are 154 * (almost) the most general case, permitting allocation in almost any 155 * way supported by the LightPulse family. The sole exception is the 156 * alignment specified as requiring memory allocation on a 4-byte boundary; 157 * the Lightpulse can DMA memory on any byte boundary. 158 * 159 * The LightPulse family currently is limited to 16M transfers; 160 * this restriction affects the dma_attr_count_max and dma_attr_maxxfer fields. 161 */ 162 ddi_dma_attr_t emlxs_dma_attr = { 163 DMA_ATTR_V0, /* dma_attr_version */ 164 (uint64_t)0, /* dma_attr_addr_lo */ 165 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */ 166 (uint64_t)0x00ffffff, /* dma_attr_count_max */ 167 1, /* dma_attr_align */ 168 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */ 169 1, /* dma_attr_minxfer */ 170 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */ 171 (uint64_t)0xffffffff, /* dma_attr_seg */ 172 1, /* dma_attr_sgllen */ 173 1, /* dma_attr_granular */ 174 0 /* dma_attr_flags */ 175 }; 176 177 ddi_dma_attr_t emlxs_dma_attr_ro = { 178 DMA_ATTR_V0, /* dma_attr_version */ 179 (uint64_t)0, /* dma_attr_addr_lo */ 180 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */ 181 (uint64_t)0x00ffffff, /* dma_attr_count_max */ 182 1, /* dma_attr_align */ 183 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */ 184 1, /* dma_attr_minxfer */ 185 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */ 186 (uint64_t)0xffffffff, /* dma_attr_seg */ 187 1, /* dma_attr_sgllen */ 188 1, /* dma_attr_granular */ 189 DDI_DMA_RELAXED_ORDERING /* dma_attr_flags */ 190 }; 191 192 ddi_dma_attr_t emlxs_dma_attr_1sg = { 193 DMA_ATTR_V0, /* dma_attr_version */ 194 (uint64_t)0, /* dma_attr_addr_lo */ 195 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */ 196 (uint64_t)0x00ffffff, /* dma_attr_count_max */ 197 1, /* dma_attr_align */ 198 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */ 199 1, /* dma_attr_minxfer */ 200 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */ 201 (uint64_t)0xffffffff, /* dma_attr_seg */ 202 1, /* dma_attr_sgllen */ 203 1, /* dma_attr_granular */ 204 0 /* dma_attr_flags */ 205 }; 206 207 #if (EMLXS_MODREV >= EMLXS_MODREV3) 208 ddi_dma_attr_t emlxs_dma_attr_fcip_rsp = { 209 DMA_ATTR_V0, /* dma_attr_version */ 210 (uint64_t)0, /* dma_attr_addr_lo */ 211 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */ 212 (uint64_t)0x00ffffff, /* dma_attr_count_max */ 213 1, /* dma_attr_align */ 214 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */ 215 1, /* dma_attr_minxfer */ 216 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */ 217 (uint64_t)0xffffffff, /* dma_attr_seg */ 218 1, /* dma_attr_sgllen */ 219 1, /* dma_attr_granular */ 220 0 /* dma_attr_flags */ 221 }; 222 #endif /* >= EMLXS_MODREV3 */ 223 224 /* 225 * DDI access attributes for device 226 */ 227 ddi_device_acc_attr_t emlxs_dev_acc_attr = { 228 DDI_DEVICE_ATTR_V1, /* devacc_attr_version */ 229 DDI_STRUCTURE_LE_ACC, /* PCI is Little Endian */ 230 DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */ 231 DDI_DEFAULT_ACC /* devacc_attr_access */ 232 }; 233 234 /* 235 * DDI access attributes for data 236 */ 237 ddi_device_acc_attr_t emlxs_data_acc_attr = { 238 DDI_DEVICE_ATTR_V1, /* devacc_attr_version */ 239 DDI_NEVERSWAP_ACC, /* don't swap for Data */ 240 DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */ 241 DDI_DEFAULT_ACC /* devacc_attr_access */ 242 }; 243 244 /* 245 * Fill in the FC Transport structure, 246 * as defined in the Fibre Channel Transport Programmming Guide. 247 */ 248 #if (EMLXS_MODREV == EMLXS_MODREV5) 249 static fc_fca_tran_t emlxs_fca_tran = { 250 FCTL_FCA_MODREV_5, /* fca_version, with SUN NPIV support */ 251 MAX_VPORTS, /* fca numerb of ports */ 252 sizeof (emlxs_buf_t), /* fca pkt size */ 253 2048, /* fca cmd max */ 254 &emlxs_dma_lim, /* fca dma limits */ 255 0, /* fca iblock, to be filled in later */ 256 &emlxs_dma_attr, /* fca dma attributes */ 257 &emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */ 258 &emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */ 259 &emlxs_dma_attr_ro, /* fca dma fcp data attributes */ 260 &emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */ 261 &emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */ 262 &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */ 263 &emlxs_dma_attr, /* fca dma fcsm rsp attributes */ 264 &emlxs_data_acc_attr, /* fca access atributes */ 265 0, /* fca_num_npivports */ 266 {{0, 0, 0, 0, 0, 0, 0, 0}}, /* Physical port WWPN */ 267 emlxs_fca_bind_port, 268 emlxs_fca_unbind_port, 269 emlxs_fca_pkt_init, 270 emlxs_fca_pkt_uninit, 271 emlxs_fca_transport, 272 emlxs_fca_get_cap, 273 emlxs_fca_set_cap, 274 emlxs_fca_get_map, 275 emlxs_fca_transport, 276 emlxs_fca_ub_alloc, 277 emlxs_fca_ub_free, 278 emlxs_fca_ub_release, 279 emlxs_fca_pkt_abort, 280 emlxs_fca_reset, 281 emlxs_fca_port_manage, 282 emlxs_fca_get_device, 283 emlxs_fca_notify 284 }; 285 #endif /* EMLXS_MODREV5 */ 286 287 288 #if (EMLXS_MODREV == EMLXS_MODREV4) 289 static fc_fca_tran_t emlxs_fca_tran = { 290 FCTL_FCA_MODREV_4, /* fca_version */ 291 MAX_VPORTS, /* fca numerb of ports */ 292 sizeof (emlxs_buf_t), /* fca pkt size */ 293 2048, /* fca cmd max */ 294 &emlxs_dma_lim, /* fca dma limits */ 295 0, /* fca iblock, to be filled in later */ 296 &emlxs_dma_attr, /* fca dma attributes */ 297 &emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */ 298 &emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */ 299 &emlxs_dma_attr_ro, /* fca dma fcp data attributes */ 300 &emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */ 301 &emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */ 302 &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */ 303 &emlxs_dma_attr, /* fca dma fcsm rsp attributes */ 304 &emlxs_data_acc_attr, /* fca access atributes */ 305 emlxs_fca_bind_port, 306 emlxs_fca_unbind_port, 307 emlxs_fca_pkt_init, 308 emlxs_fca_pkt_uninit, 309 emlxs_fca_transport, 310 emlxs_fca_get_cap, 311 emlxs_fca_set_cap, 312 emlxs_fca_get_map, 313 emlxs_fca_transport, 314 emlxs_fca_ub_alloc, 315 emlxs_fca_ub_free, 316 emlxs_fca_ub_release, 317 emlxs_fca_pkt_abort, 318 emlxs_fca_reset, 319 emlxs_fca_port_manage, 320 emlxs_fca_get_device, 321 emlxs_fca_notify 322 }; 323 #endif /* EMLXS_MODEREV4 */ 324 325 326 #if (EMLXS_MODREV == EMLXS_MODREV3) 327 static fc_fca_tran_t emlxs_fca_tran = { 328 FCTL_FCA_MODREV_3, /* fca_version */ 329 MAX_VPORTS, /* fca numerb of ports */ 330 sizeof (emlxs_buf_t), /* fca pkt size */ 331 2048, /* fca cmd max */ 332 &emlxs_dma_lim, /* fca dma limits */ 333 0, /* fca iblock, to be filled in later */ 334 &emlxs_dma_attr, /* fca dma attributes */ 335 &emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */ 336 &emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */ 337 &emlxs_dma_attr_ro, /* fca dma fcp data attributes */ 338 &emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */ 339 &emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */ 340 &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */ 341 &emlxs_dma_attr, /* fca dma fcsm rsp attributes */ 342 &emlxs_data_acc_attr, /* fca access atributes */ 343 emlxs_fca_bind_port, 344 emlxs_fca_unbind_port, 345 emlxs_fca_pkt_init, 346 emlxs_fca_pkt_uninit, 347 emlxs_fca_transport, 348 emlxs_fca_get_cap, 349 emlxs_fca_set_cap, 350 emlxs_fca_get_map, 351 emlxs_fca_transport, 352 emlxs_fca_ub_alloc, 353 emlxs_fca_ub_free, 354 emlxs_fca_ub_release, 355 emlxs_fca_pkt_abort, 356 emlxs_fca_reset, 357 emlxs_fca_port_manage, 358 emlxs_fca_get_device, 359 emlxs_fca_notify 360 }; 361 #endif /* EMLXS_MODREV3 */ 362 363 364 #if (EMLXS_MODREV == EMLXS_MODREV2) 365 static fc_fca_tran_t emlxs_fca_tran = { 366 FCTL_FCA_MODREV_2, /* fca_version */ 367 MAX_VPORTS, /* number of ports */ 368 sizeof (emlxs_buf_t), /* pkt size */ 369 2048, /* max cmds */ 370 &emlxs_dma_lim, /* DMA limits */ 371 0, /* iblock, to be filled in later */ 372 &emlxs_dma_attr, /* dma attributes */ 373 &emlxs_data_acc_attr, /* access atributes */ 374 emlxs_fca_bind_port, 375 emlxs_fca_unbind_port, 376 emlxs_fca_pkt_init, 377 emlxs_fca_pkt_uninit, 378 emlxs_fca_transport, 379 emlxs_fca_get_cap, 380 emlxs_fca_set_cap, 381 emlxs_fca_get_map, 382 emlxs_fca_transport, 383 emlxs_fca_ub_alloc, 384 emlxs_fca_ub_free, 385 emlxs_fca_ub_release, 386 emlxs_fca_pkt_abort, 387 emlxs_fca_reset, 388 emlxs_fca_port_manage, 389 emlxs_fca_get_device, 390 emlxs_fca_notify 391 }; 392 #endif /* EMLXS_MODREV2 */ 393 394 395 /* 396 * state pointer which the implementation uses as a place to 397 * hang a set of per-driver structures; 398 * 399 */ 400 void *emlxs_soft_state = NULL; 401 402 /* 403 * Driver Global variables. 404 */ 405 int32_t emlxs_scsi_reset_delay = 3000; /* milliseconds */ 406 407 emlxs_device_t emlxs_device; 408 409 uint32_t emlxs_instance[MAX_FC_BRDS]; /* uses emlxs_device.lock */ 410 uint32_t emlxs_instance_count = 0; /* uses emlxs_device.lock */ 411 uint32_t emlxs_instance_flag = 0; /* uses emlxs_device.lock */ 412 #define EMLXS_FW_SHOW 0x00000001 413 414 415 /* 416 * CB ops vector. Used for administration only. 417 */ 418 static struct cb_ops emlxs_cb_ops = { 419 emlxs_open, /* cb_open */ 420 emlxs_close, /* cb_close */ 421 nodev, /* cb_strategy */ 422 nodev, /* cb_print */ 423 nodev, /* cb_dump */ 424 nodev, /* cb_read */ 425 nodev, /* cb_write */ 426 emlxs_ioctl, /* cb_ioctl */ 427 nodev, /* cb_devmap */ 428 nodev, /* cb_mmap */ 429 nodev, /* cb_segmap */ 430 nochpoll, /* cb_chpoll */ 431 ddi_prop_op, /* cb_prop_op */ 432 0, /* cb_stream */ 433 #ifdef _LP64 434 D_64BIT | D_HOTPLUG | D_MP | D_NEW, /* cb_flag */ 435 #else 436 D_HOTPLUG | D_MP | D_NEW, /* cb_flag */ 437 #endif 438 CB_REV, /* rev */ 439 nodev, /* cb_aread */ 440 nodev /* cb_awrite */ 441 }; 442 443 static struct dev_ops emlxs_ops = { 444 DEVO_REV, /* rev */ 445 0, /* refcnt */ 446 emlxs_info, /* getinfo */ 447 nulldev, /* identify */ 448 nulldev, /* probe */ 449 emlxs_attach, /* attach */ 450 emlxs_detach, /* detach */ 451 nodev, /* reset */ 452 &emlxs_cb_ops, /* devo_cb_ops */ 453 NULL, /* devo_bus_ops */ 454 emlxs_power, /* power ops */ 455 #ifdef EMLXS_I386 456 #ifdef S11 457 emlxs_quiesce, /* quiesce */ 458 #endif /* S11 */ 459 #endif /* EMLXS_I386 */ 460 }; 461 462 #include <sys/modctl.h> 463 extern struct mod_ops mod_driverops; 464 465 #ifdef SAN_DIAG_SUPPORT 466 extern kmutex_t emlxs_sd_bucket_mutex; 467 extern sd_bucket_info_t emlxs_sd_bucket; 468 #endif /* SAN_DIAG_SUPPORT */ 469 470 /* 471 * Module linkage information for the kernel. 472 */ 473 static struct modldrv emlxs_modldrv = { 474 &mod_driverops, /* module type - driver */ 475 emlxs_name, /* module name */ 476 &emlxs_ops, /* driver ops */ 477 }; 478 479 480 /* 481 * Driver module linkage structure 482 */ 483 static struct modlinkage emlxs_modlinkage = { 484 MODREV_1, /* ml_rev - must be MODREV_1 */ 485 { &emlxs_modldrv, /* ml_linkage */ 486 NULL } 487 }; 488 489 490 /* We only need to add entries for non-default return codes. */ 491 /* Entries do not need to be in order. */ 492 /* Default: FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, */ 493 /* FC_EXPLN_NONE, FC_ACTION_RETRYABLE */ 494 495 emlxs_xlat_err_t emlxs_iostat_tbl[] = { 496 /* {f/w code, pkt_state, pkt_reason, */ 497 /* pkt_expln, pkt_action} */ 498 499 /* 0x00 - Do not remove */ 500 {IOSTAT_SUCCESS, FC_PKT_SUCCESS, FC_REASON_NONE, 501 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 502 503 /* 0x01 - Do not remove */ 504 {IOSTAT_FCP_RSP_ERROR, FC_PKT_SUCCESS, FC_REASON_NONE, 505 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 506 507 /* 0x02 */ 508 {IOSTAT_REMOTE_STOP, FC_PKT_REMOTE_STOP, FC_REASON_ABTS, 509 FC_EXPLN_NONE, FC_ACTION_NON_RETRYABLE}, 510 511 /* 512 * This is a default entry. 513 * The real codes are written dynamically in emlxs_els.c 514 */ 515 /* 0x09 */ 516 {IOSTAT_LS_RJT, FC_PKT_LS_RJT, FC_REASON_CMD_UNABLE, 517 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 518 519 /* Special error code */ 520 /* 0x10 */ 521 {IOSTAT_DATA_OVERRUN, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN, 522 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 523 524 /* Special error code */ 525 /* 0x11 */ 526 {IOSTAT_DATA_UNDERRUN, FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, 527 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 528 529 /* Special error code */ 530 /* 0x12 */ 531 {IOSTAT_RSP_INVALID, FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, 532 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 533 534 /* CLASS 2 only */ 535 /* 0x04 */ 536 {IOSTAT_NPORT_RJT, FC_PKT_NPORT_RJT, FC_REASON_PROTOCOL_ERROR, 537 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 538 539 /* CLASS 2 only */ 540 /* 0x05 */ 541 {IOSTAT_FABRIC_RJT, FC_PKT_FABRIC_RJT, FC_REASON_PROTOCOL_ERROR, 542 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 543 544 /* CLASS 2 only */ 545 /* 0x06 */ 546 {IOSTAT_NPORT_BSY, FC_PKT_NPORT_BSY, FC_REASON_PHYSICAL_BUSY, 547 FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY}, 548 549 /* CLASS 2 only */ 550 /* 0x07 */ 551 {IOSTAT_FABRIC_BSY, FC_PKT_FABRIC_BSY, FC_REASON_FABRIC_BSY, 552 FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY}, 553 }; 554 555 #define IOSTAT_MAX (sizeof (emlxs_iostat_tbl)/sizeof (emlxs_xlat_err_t)) 556 557 558 /* We only need to add entries for non-default return codes. */ 559 /* Entries do not need to be in order. */ 560 /* Default: FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, */ 561 /* FC_EXPLN_NONE, FC_ACTION_RETRYABLE} */ 562 563 emlxs_xlat_err_t emlxs_ioerr_tbl[] = { 564 /* {f/w code, pkt_state, pkt_reason, */ 565 /* pkt_expln, pkt_action} */ 566 567 /* 0x01 */ 568 {IOERR_MISSING_CONTINUE, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN, 569 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 570 571 /* 0x02 */ 572 {IOERR_SEQUENCE_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT, 573 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 574 575 /* 0x04 */ 576 {IOERR_INVALID_RPI, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE, 577 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 578 579 /* 0x05 */ 580 {IOERR_NO_XRI, FC_PKT_LOCAL_RJT, FC_REASON_XCHG_DROPPED, 581 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 582 583 /* 0x06 */ 584 {IOERR_ILLEGAL_COMMAND, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_REQ, 585 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 586 587 /* 0x07 */ 588 {IOERR_XCHG_DROPPED, FC_PKT_LOCAL_RJT, FC_REASON_XCHG_DROPPED, 589 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 590 591 /* 0x08 */ 592 {IOERR_ILLEGAL_FIELD, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_REQ, 593 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 594 595 /* 0x0B */ 596 {IOERR_RCV_BUFFER_WAITING, FC_PKT_LOCAL_RJT, FC_REASON_NOMEM, 597 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 598 599 /* 0x0D */ 600 {IOERR_TX_DMA_FAILED, FC_PKT_LOCAL_RJT, FC_REASON_DMA_ERROR, 601 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 602 603 /* 0x0E */ 604 {IOERR_RX_DMA_FAILED, FC_PKT_LOCAL_RJT, FC_REASON_DMA_ERROR, 605 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 606 607 /* 0x0F */ 608 {IOERR_ILLEGAL_FRAME, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_FRAME, 609 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 610 611 /* 0x11 */ 612 {IOERR_NO_RESOURCES, FC_PKT_LOCAL_RJT, FC_REASON_NOMEM, 613 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 614 615 /* 0x13 */ 616 {IOERR_ILLEGAL_LENGTH, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_LENGTH, 617 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 618 619 /* 0x14 */ 620 {IOERR_UNSUPPORTED_FEATURE, FC_PKT_LOCAL_RJT, FC_REASON_UNSUPPORTED, 621 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 622 623 /* 0x15 */ 624 {IOERR_ABORT_IN_PROGRESS, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED, 625 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 626 627 /* 0x16 */ 628 {IOERR_ABORT_REQUESTED, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED, 629 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 630 631 /* 0x17 */ 632 {IOERR_RCV_BUFFER_TIMEOUT, FC_PKT_LOCAL_RJT, FC_REASON_RX_BUF_TIMEOUT, 633 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 634 635 /* 0x18 */ 636 {IOERR_LOOP_OPEN_FAILURE, FC_PKT_LOCAL_RJT, FC_REASON_FCAL_OPN_FAIL, 637 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 638 639 /* 0x1A */ 640 {IOERR_LINK_DOWN, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE, 641 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 642 643 /* 0x21 */ 644 {IOERR_BAD_HOST_ADDRESS, FC_PKT_LOCAL_RJT, FC_REASON_BAD_SID, 645 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 646 647 /* Occurs at link down */ 648 /* 0x28 */ 649 {IOERR_BUFFER_SHORTAGE, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE, 650 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 651 652 /* 0xF0 */ 653 {IOERR_ABORT_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT, 654 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 655 }; 656 657 #define IOERR_MAX (sizeof (emlxs_ioerr_tbl)/sizeof (emlxs_xlat_err_t)) 658 659 660 661 emlxs_table_t emlxs_error_table[] = { 662 {IOERR_SUCCESS, "No error."}, 663 {IOERR_MISSING_CONTINUE, "Missing continue."}, 664 {IOERR_SEQUENCE_TIMEOUT, "Sequence timeout."}, 665 {IOERR_INTERNAL_ERROR, "Internal error."}, 666 {IOERR_INVALID_RPI, "Invalid RPI."}, 667 {IOERR_NO_XRI, "No XRI."}, 668 {IOERR_ILLEGAL_COMMAND, "Illegal command."}, 669 {IOERR_XCHG_DROPPED, "Exchange dropped."}, 670 {IOERR_ILLEGAL_FIELD, "Illegal field."}, 671 {IOERR_RCV_BUFFER_WAITING, "RX buffer waiting."}, 672 {IOERR_TX_DMA_FAILED, "TX DMA failed."}, 673 {IOERR_RX_DMA_FAILED, "RX DMA failed."}, 674 {IOERR_ILLEGAL_FRAME, "Illegal frame."}, 675 {IOERR_NO_RESOURCES, "No resources."}, 676 {IOERR_ILLEGAL_LENGTH, "Illegal length."}, 677 {IOERR_UNSUPPORTED_FEATURE, "Unsupported feature."}, 678 {IOERR_ABORT_IN_PROGRESS, "Abort in progess."}, 679 {IOERR_ABORT_REQUESTED, "Abort requested."}, 680 {IOERR_RCV_BUFFER_TIMEOUT, "RX buffer timeout."}, 681 {IOERR_LOOP_OPEN_FAILURE, "Loop open failed."}, 682 {IOERR_RING_RESET, "Ring reset."}, 683 {IOERR_LINK_DOWN, "Link down."}, 684 {IOERR_CORRUPTED_DATA, "Corrupted data."}, 685 {IOERR_CORRUPTED_RPI, "Corrupted RPI."}, 686 {IOERR_OUT_OF_ORDER_DATA, "Out-of-order data."}, 687 {IOERR_OUT_OF_ORDER_ACK, "Out-of-order ack."}, 688 {IOERR_DUP_FRAME, "Duplicate frame."}, 689 {IOERR_LINK_CONTROL_FRAME, "Link control frame."}, 690 {IOERR_BAD_HOST_ADDRESS, "Bad host address."}, 691 {IOERR_RCV_HDRBUF_WAITING, "RX header buffer waiting."}, 692 {IOERR_MISSING_HDR_BUFFER, "Missing header buffer."}, 693 {IOERR_MSEQ_CHAIN_CORRUPTED, "MSEQ chain corrupted."}, 694 {IOERR_ABORTMULT_REQUESTED, "Abort multiple requested."}, 695 {IOERR_BUFFER_SHORTAGE, "Buffer shortage."}, 696 {IOERR_XRIBUF_WAITING, "XRI buffer shortage"}, 697 {IOERR_XRIBUF_MISSING, "XRI buffer missing"}, 698 {IOERR_ROFFSET_INVAL, "Relative offset invalid."}, 699 {IOERR_ROFFSET_MISSING, "Relative offset missing."}, 700 {IOERR_INSUF_BUFFER, "Buffer too small."}, 701 {IOERR_MISSING_SI, "ELS frame missing SI"}, 702 {IOERR_MISSING_ES, "Exhausted burst without ES"}, 703 {IOERR_INCOMP_XFER, "Transfer incomplete."}, 704 {IOERR_ABORT_TIMEOUT, "Abort timeout."} 705 706 }; /* emlxs_error_table */ 707 708 709 emlxs_table_t emlxs_state_table[] = { 710 {IOSTAT_SUCCESS, "Success."}, 711 {IOSTAT_FCP_RSP_ERROR, "FCP response error."}, 712 {IOSTAT_REMOTE_STOP, "Remote stop."}, 713 {IOSTAT_LOCAL_REJECT, "Local reject."}, 714 {IOSTAT_NPORT_RJT, "NPort reject."}, 715 {IOSTAT_FABRIC_RJT, "Fabric reject."}, 716 {IOSTAT_NPORT_BSY, "Nport busy."}, 717 {IOSTAT_FABRIC_BSY, "Fabric busy."}, 718 {IOSTAT_INTERMED_RSP, "Intermediate response."}, 719 {IOSTAT_LS_RJT, "LS reject."}, 720 {IOSTAT_CMD_REJECT, "Cmd reject."}, 721 {IOSTAT_FCP_TGT_LENCHK, "TGT length check."}, 722 {IOSTAT_NEED_BUFF_ENTRY, "Need buffer entry."}, 723 {IOSTAT_DATA_UNDERRUN, "Data underrun."}, 724 {IOSTAT_DATA_OVERRUN, "Data overrun."}, 725 {IOSTAT_RSP_INVALID, "Response Invalid."}, 726 727 }; /* emlxs_state_table */ 728 729 730 #ifdef MENLO_SUPPORT 731 emlxs_table_t emlxs_menlo_cmd_table[] = { 732 {MENLO_CMD_INITIALIZE, "MENLO_INIT"}, 733 {MENLO_CMD_FW_DOWNLOAD, "MENLO_FW_DOWNLOAD"}, 734 {MENLO_CMD_READ_MEMORY, "MENLO_READ_MEM"}, 735 {MENLO_CMD_WRITE_MEMORY, "MENLO_WRITE_MEM"}, 736 {MENLO_CMD_FTE_INSERT, "MENLO_FTE_INSERT"}, 737 {MENLO_CMD_FTE_DELETE, "MENLO_FTE_DELETE"}, 738 739 {MENLO_CMD_GET_INIT, "MENLO_GET_INIT"}, 740 {MENLO_CMD_GET_CONFIG, "MENLO_GET_CONFIG"}, 741 {MENLO_CMD_GET_PORT_STATS, "MENLO_GET_PORT_STATS"}, 742 {MENLO_CMD_GET_LIF_STATS, "MENLO_GET_LIF_STATS"}, 743 {MENLO_CMD_GET_ASIC_STATS, "MENLO_GET_ASIC_STATS"}, 744 {MENLO_CMD_GET_LOG_CONFIG, "MENLO_GET_LOG_CFG"}, 745 {MENLO_CMD_GET_LOG_DATA, "MENLO_GET_LOG_DATA"}, 746 {MENLO_CMD_GET_PANIC_LOG, "MENLO_GET_PANIC_LOG"}, 747 {MENLO_CMD_GET_LB_MODE, "MENLO_GET_LB_MODE"}, 748 749 {MENLO_CMD_SET_PAUSE, "MENLO_SET_PAUSE"}, 750 {MENLO_CMD_SET_FCOE_COS, "MENLO_SET_FCOE_COS"}, 751 {MENLO_CMD_SET_UIF_PORT_TYPE, "MENLO_SET_UIF_TYPE"}, 752 753 {MENLO_CMD_DIAGNOSTICS, "MENLO_DIAGNOSTICS"}, 754 {MENLO_CMD_LOOPBACK, "MENLO_LOOPBACK"}, 755 756 {MENLO_CMD_RESET, "MENLO_RESET"}, 757 {MENLO_CMD_SET_MODE, "MENLO_SET_MODE"} 758 759 }; /* emlxs_menlo_cmd_table */ 760 761 emlxs_table_t emlxs_menlo_rsp_table[] = { 762 {MENLO_RSP_SUCCESS, "SUCCESS"}, 763 {MENLO_ERR_FAILED, "FAILED"}, 764 {MENLO_ERR_INVALID_CMD, "INVALID_CMD"}, 765 {MENLO_ERR_INVALID_CREDIT, "INVALID_CREDIT"}, 766 {MENLO_ERR_INVALID_SIZE, "INVALID_SIZE"}, 767 {MENLO_ERR_INVALID_ADDRESS, "INVALID_ADDRESS"}, 768 {MENLO_ERR_INVALID_CONTEXT, "INVALID_CONTEXT"}, 769 {MENLO_ERR_INVALID_LENGTH, "INVALID_LENGTH"}, 770 {MENLO_ERR_INVALID_TYPE, "INVALID_TYPE"}, 771 {MENLO_ERR_INVALID_DATA, "INVALID_DATA"}, 772 {MENLO_ERR_INVALID_VALUE1, "INVALID_VALUE1"}, 773 {MENLO_ERR_INVALID_VALUE2, "INVALID_VALUE2"}, 774 {MENLO_ERR_INVALID_MASK, "INVALID_MASK"}, 775 {MENLO_ERR_CHECKSUM, "CHECKSUM_ERROR"}, 776 {MENLO_ERR_UNKNOWN_FCID, "UNKNOWN_FCID"}, 777 {MENLO_ERR_UNKNOWN_WWN, "UNKNOWN_WWN"}, 778 {MENLO_ERR_BUSY, "BUSY"}, 779 780 }; /* emlxs_menlo_rsp_table */ 781 782 #endif /* MENLO_SUPPORT */ 783 784 785 emlxs_table_t emlxs_mscmd_table[] = { 786 {SLI_CT_RESPONSE_FS_ACC, "CT_ACC"}, 787 {SLI_CT_RESPONSE_FS_RJT, "CT_RJT"}, 788 {MS_GTIN, "MS_GTIN"}, 789 {MS_GIEL, "MS_GIEL"}, 790 {MS_GIET, "MS_GIET"}, 791 {MS_GDID, "MS_GDID"}, 792 {MS_GMID, "MS_GMID"}, 793 {MS_GFN, "MS_GFN"}, 794 {MS_GIELN, "MS_GIELN"}, 795 {MS_GMAL, "MS_GMAL"}, 796 {MS_GIEIL, "MS_GIEIL"}, 797 {MS_GPL, "MS_GPL"}, 798 {MS_GPT, "MS_GPT"}, 799 {MS_GPPN, "MS_GPPN"}, 800 {MS_GAPNL, "MS_GAPNL"}, 801 {MS_GPS, "MS_GPS"}, 802 {MS_GPSC, "MS_GPSC"}, 803 {MS_GATIN, "MS_GATIN"}, 804 {MS_GSES, "MS_GSES"}, 805 {MS_GPLNL, "MS_GPLNL"}, 806 {MS_GPLT, "MS_GPLT"}, 807 {MS_GPLML, "MS_GPLML"}, 808 {MS_GPAB, "MS_GPAB"}, 809 {MS_GNPL, "MS_GNPL"}, 810 {MS_GPNL, "MS_GPNL"}, 811 {MS_GPFCP, "MS_GPFCP"}, 812 {MS_GPLI, "MS_GPLI"}, 813 {MS_GNID, "MS_GNID"}, 814 {MS_RIELN, "MS_RIELN"}, 815 {MS_RPL, "MS_RPL"}, 816 {MS_RPLN, "MS_RPLN"}, 817 {MS_RPLT, "MS_RPLT"}, 818 {MS_RPLM, "MS_RPLM"}, 819 {MS_RPAB, "MS_RPAB"}, 820 {MS_RPFCP, "MS_RPFCP"}, 821 {MS_RPLI, "MS_RPLI"}, 822 {MS_DPL, "MS_DPL"}, 823 {MS_DPLN, "MS_DPLN"}, 824 {MS_DPLM, "MS_DPLM"}, 825 {MS_DPLML, "MS_DPLML"}, 826 {MS_DPLI, "MS_DPLI"}, 827 {MS_DPAB, "MS_DPAB"}, 828 {MS_DPALL, "MS_DPALL"} 829 830 }; /* emlxs_mscmd_table */ 831 832 833 emlxs_table_t emlxs_ctcmd_table[] = { 834 {SLI_CT_RESPONSE_FS_ACC, "CT_ACC"}, 835 {SLI_CT_RESPONSE_FS_RJT, "CT_RJT"}, 836 {SLI_CTNS_GA_NXT, "GA_NXT"}, 837 {SLI_CTNS_GPN_ID, "GPN_ID"}, 838 {SLI_CTNS_GNN_ID, "GNN_ID"}, 839 {SLI_CTNS_GCS_ID, "GCS_ID"}, 840 {SLI_CTNS_GFT_ID, "GFT_ID"}, 841 {SLI_CTNS_GSPN_ID, "GSPN_ID"}, 842 {SLI_CTNS_GPT_ID, "GPT_ID"}, 843 {SLI_CTNS_GID_PN, "GID_PN"}, 844 {SLI_CTNS_GID_NN, "GID_NN"}, 845 {SLI_CTNS_GIP_NN, "GIP_NN"}, 846 {SLI_CTNS_GIPA_NN, "GIPA_NN"}, 847 {SLI_CTNS_GSNN_NN, "GSNN_NN"}, 848 {SLI_CTNS_GNN_IP, "GNN_IP"}, 849 {SLI_CTNS_GIPA_IP, "GIPA_IP"}, 850 {SLI_CTNS_GID_FT, "GID_FT"}, 851 {SLI_CTNS_GID_PT, "GID_PT"}, 852 {SLI_CTNS_RPN_ID, "RPN_ID"}, 853 {SLI_CTNS_RNN_ID, "RNN_ID"}, 854 {SLI_CTNS_RCS_ID, "RCS_ID"}, 855 {SLI_CTNS_RFT_ID, "RFT_ID"}, 856 {SLI_CTNS_RSPN_ID, "RSPN_ID"}, 857 {SLI_CTNS_RPT_ID, "RPT_ID"}, 858 {SLI_CTNS_RIP_NN, "RIP_NN"}, 859 {SLI_CTNS_RIPA_NN, "RIPA_NN"}, 860 {SLI_CTNS_RSNN_NN, "RSNN_NN"}, 861 {SLI_CTNS_DA_ID, "DA_ID"}, 862 {SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */ 863 864 }; /* emlxs_ctcmd_table */ 865 866 867 868 emlxs_table_t emlxs_rmcmd_table[] = { 869 {SLI_CT_RESPONSE_FS_ACC, "CT_ACC"}, 870 {SLI_CT_RESPONSE_FS_RJT, "CT_RJT"}, 871 {CT_OP_GSAT, "RM_GSAT"}, 872 {CT_OP_GHAT, "RM_GHAT"}, 873 {CT_OP_GPAT, "RM_GPAT"}, 874 {CT_OP_GDAT, "RM_GDAT"}, 875 {CT_OP_GPST, "RM_GPST"}, 876 {CT_OP_GDP, "RM_GDP"}, 877 {CT_OP_GDPG, "RM_GDPG"}, 878 {CT_OP_GEPS, "RM_GEPS"}, 879 {CT_OP_GLAT, "RM_GLAT"}, 880 {CT_OP_SSAT, "RM_SSAT"}, 881 {CT_OP_SHAT, "RM_SHAT"}, 882 {CT_OP_SPAT, "RM_SPAT"}, 883 {CT_OP_SDAT, "RM_SDAT"}, 884 {CT_OP_SDP, "RM_SDP"}, 885 {CT_OP_SBBS, "RM_SBBS"}, 886 {CT_OP_RPST, "RM_RPST"}, 887 {CT_OP_VFW, "RM_VFW"}, 888 {CT_OP_DFW, "RM_DFW"}, 889 {CT_OP_RES, "RM_RES"}, 890 {CT_OP_RHD, "RM_RHD"}, 891 {CT_OP_UFW, "RM_UFW"}, 892 {CT_OP_RDP, "RM_RDP"}, 893 {CT_OP_GHDR, "RM_GHDR"}, 894 {CT_OP_CHD, "RM_CHD"}, 895 {CT_OP_SSR, "RM_SSR"}, 896 {CT_OP_RSAT, "RM_RSAT"}, 897 {CT_OP_WSAT, "RM_WSAT"}, 898 {CT_OP_RSAH, "RM_RSAH"}, 899 {CT_OP_WSAH, "RM_WSAH"}, 900 {CT_OP_RACT, "RM_RACT"}, 901 {CT_OP_WACT, "RM_WACT"}, 902 {CT_OP_RKT, "RM_RKT"}, 903 {CT_OP_WKT, "RM_WKT"}, 904 {CT_OP_SSC, "RM_SSC"}, 905 {CT_OP_QHBA, "RM_QHBA"}, 906 {CT_OP_GST, "RM_GST"}, 907 {CT_OP_GFTM, "RM_GFTM"}, 908 {CT_OP_SRL, "RM_SRL"}, 909 {CT_OP_SI, "RM_SI"}, 910 {CT_OP_SRC, "RM_SRC"}, 911 {CT_OP_GPB, "RM_GPB"}, 912 {CT_OP_SPB, "RM_SPB"}, 913 {CT_OP_RPB, "RM_RPB"}, 914 {CT_OP_RAPB, "RM_RAPB"}, 915 {CT_OP_GBC, "RM_GBC"}, 916 {CT_OP_GBS, "RM_GBS"}, 917 {CT_OP_SBS, "RM_SBS"}, 918 {CT_OP_GANI, "RM_GANI"}, 919 {CT_OP_GRV, "RM_GRV"}, 920 {CT_OP_GAPBS, "RM_GAPBS"}, 921 {CT_OP_APBC, "RM_APBC"}, 922 {CT_OP_GDT, "RM_GDT"}, 923 {CT_OP_GDLMI, "RM_GDLMI"}, 924 {CT_OP_GANA, "RM_GANA"}, 925 {CT_OP_GDLV, "RM_GDLV"}, 926 {CT_OP_GWUP, "RM_GWUP"}, 927 {CT_OP_GLM, "RM_GLM"}, 928 {CT_OP_GABS, "RM_GABS"}, 929 {CT_OP_SABS, "RM_SABS"}, 930 {CT_OP_RPR, "RM_RPR"}, 931 {SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */ 932 933 }; /* emlxs_rmcmd_table */ 934 935 936 emlxs_table_t emlxs_elscmd_table[] = { 937 {ELS_CMD_ACC, "ACC"}, 938 {ELS_CMD_LS_RJT, "LS_RJT"}, 939 {ELS_CMD_PLOGI, "PLOGI"}, 940 {ELS_CMD_FLOGI, "FLOGI"}, 941 {ELS_CMD_LOGO, "LOGO"}, 942 {ELS_CMD_ABTX, "ABTX"}, 943 {ELS_CMD_RCS, "RCS"}, 944 {ELS_CMD_RES, "RES"}, 945 {ELS_CMD_RSS, "RSS"}, 946 {ELS_CMD_RSI, "RSI"}, 947 {ELS_CMD_ESTS, "ESTS"}, 948 {ELS_CMD_ESTC, "ESTC"}, 949 {ELS_CMD_ADVC, "ADVC"}, 950 {ELS_CMD_RTV, "RTV"}, 951 {ELS_CMD_RLS, "RLS"}, 952 {ELS_CMD_ECHO, "ECHO"}, 953 {ELS_CMD_TEST, "TEST"}, 954 {ELS_CMD_RRQ, "RRQ"}, 955 {ELS_CMD_REC, "REC"}, 956 {ELS_CMD_PRLI, "PRLI"}, 957 {ELS_CMD_PRLO, "PRLO"}, 958 {ELS_CMD_SCN, "SCN"}, 959 {ELS_CMD_TPLS, "TPLS"}, 960 {ELS_CMD_GPRLO, "GPRLO"}, 961 {ELS_CMD_GAID, "GAID"}, 962 {ELS_CMD_FACT, "FACT"}, 963 {ELS_CMD_FDACT, "FDACT"}, 964 {ELS_CMD_NACT, "NACT"}, 965 {ELS_CMD_NDACT, "NDACT"}, 966 {ELS_CMD_QoSR, "QoSR"}, 967 {ELS_CMD_RVCS, "RVCS"}, 968 {ELS_CMD_PDISC, "PDISC"}, 969 {ELS_CMD_FDISC, "FDISC"}, 970 {ELS_CMD_ADISC, "ADISC"}, 971 {ELS_CMD_FARP, "FARP"}, 972 {ELS_CMD_FARPR, "FARPR"}, 973 {ELS_CMD_FAN, "FAN"}, 974 {ELS_CMD_RSCN, "RSCN"}, 975 {ELS_CMD_SCR, "SCR"}, 976 {ELS_CMD_LINIT, "LINIT"}, 977 {ELS_CMD_RNID, "RNID"}, 978 {ELS_CMD_AUTH, "AUTH"} 979 980 }; /* emlxs_elscmd_table */ 981 982 983 emlxs_table_t emlxs_mode_table[] = { 984 {MODE_NONE, "NONE"}, 985 {MODE_INITIATOR, "INITIATOR"}, 986 {MODE_TARGET, "TARGET"}, 987 {MODE_ALL, "INITIATOR | TARGET"} 988 }; /* emlxs_mode_table */ 989 990 /* 991 * 992 * Device Driver Entry Routines 993 * 994 */ 995 996 #ifdef MODSYM_SUPPORT 997 static void emlxs_fca_modclose(); 998 static int emlxs_fca_modopen(); 999 emlxs_modsym_t emlxs_modsym; /* uses emlxs_device.lock */ 1000 1001 static int 1002 emlxs_fca_modopen() 1003 { 1004 int err; 1005 1006 if (emlxs_modsym.mod_fctl) { 1007 return (0); 1008 } 1009 1010 /* Leadville (fctl) */ 1011 err = 0; 1012 emlxs_modsym.mod_fctl = 1013 ddi_modopen("misc/fctl", KRTLD_MODE_FIRST, &err); 1014 if (!emlxs_modsym.mod_fctl) { 1015 cmn_err(CE_WARN, 1016 "?%s: misc/fctl: ddi_modopen misc/fctl failed: error=%d", 1017 DRIVER_NAME, err); 1018 1019 goto failed; 1020 } 1021 1022 err = 0; 1023 /* Check if the fctl fc_fca_attach is present */ 1024 emlxs_modsym.fc_fca_attach = 1025 (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_attach", 1026 &err); 1027 if ((void *)emlxs_modsym.fc_fca_attach == NULL) { 1028 cmn_err(CE_WARN, 1029 "?%s: misc/fctl: fc_fca_attach not present", DRIVER_NAME); 1030 goto failed; 1031 } 1032 1033 err = 0; 1034 /* Check if the fctl fc_fca_detach is present */ 1035 emlxs_modsym.fc_fca_detach = 1036 (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_detach", 1037 &err); 1038 if ((void *)emlxs_modsym.fc_fca_detach == NULL) { 1039 cmn_err(CE_WARN, 1040 "?%s: misc/fctl: fc_fca_detach not present", DRIVER_NAME); 1041 goto failed; 1042 } 1043 1044 err = 0; 1045 /* Check if the fctl fc_fca_init is present */ 1046 emlxs_modsym.fc_fca_init = 1047 (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_init", &err); 1048 if ((void *)emlxs_modsym.fc_fca_init == NULL) { 1049 cmn_err(CE_WARN, 1050 "?%s: misc/fctl: fc_fca_init not present", DRIVER_NAME); 1051 goto failed; 1052 } 1053 1054 return (0); 1055 1056 failed: 1057 1058 emlxs_fca_modclose(); 1059 1060 return (1); 1061 1062 1063 } /* emlxs_fca_modopen() */ 1064 1065 1066 static void 1067 emlxs_fca_modclose() 1068 { 1069 if (emlxs_modsym.mod_fctl) { 1070 (void) ddi_modclose(emlxs_modsym.mod_fctl); 1071 emlxs_modsym.mod_fctl = 0; 1072 } 1073 1074 emlxs_modsym.fc_fca_attach = NULL; 1075 emlxs_modsym.fc_fca_detach = NULL; 1076 emlxs_modsym.fc_fca_init = NULL; 1077 1078 return; 1079 1080 } /* emlxs_fca_modclose() */ 1081 1082 #endif /* MODSYM_SUPPORT */ 1083 1084 1085 1086 /* 1087 * Global driver initialization, called once when driver is loaded 1088 */ 1089 int 1090 _init(void) 1091 { 1092 int ret; 1093 1094 /* 1095 * First init call for this driver, 1096 * so initialize the emlxs_dev_ctl structure. 1097 */ 1098 bzero(&emlxs_device, sizeof (emlxs_device)); 1099 1100 #ifdef MODSYM_SUPPORT 1101 bzero(&emlxs_modsym, sizeof (emlxs_modsym_t)); 1102 #endif /* MODSYM_SUPPORT */ 1103 1104 mutex_init(&emlxs_device.lock, NULL, MUTEX_DRIVER, NULL); 1105 1106 (void) drv_getparm(LBOLT, &emlxs_device.log_timestamp); 1107 emlxs_device.drv_timestamp = ddi_get_time(); 1108 1109 for (ret = 0; ret < MAX_FC_BRDS; ret++) { 1110 emlxs_instance[ret] = (uint32_t)-1; 1111 } 1112 1113 /* 1114 * Provide for one ddiinst of the emlxs_dev_ctl structure 1115 * for each possible board in the system. 1116 */ 1117 if ((ret = ddi_soft_state_init(&emlxs_soft_state, 1118 sizeof (emlxs_hba_t), MAX_FC_BRDS)) != 0) { 1119 cmn_err(CE_WARN, 1120 "?%s: _init: ddi_soft_state_init failed. rval=%x", 1121 DRIVER_NAME, ret); 1122 1123 return (ret); 1124 } 1125 1126 #ifdef MODSYM_SUPPORT 1127 /* Open SFS */ 1128 (void) emlxs_fca_modopen(); 1129 #endif /* MODSYM_SUPPORT */ 1130 1131 /* Setup devops for SFS */ 1132 MODSYM(fc_fca_init)(&emlxs_ops); 1133 1134 if ((ret = mod_install(&emlxs_modlinkage)) != 0) { 1135 (void) ddi_soft_state_fini(&emlxs_soft_state); 1136 #ifdef MODSYM_SUPPORT 1137 /* Close SFS */ 1138 emlxs_fca_modclose(); 1139 #endif /* MODSYM_SUPPORT */ 1140 1141 return (ret); 1142 } 1143 1144 #ifdef SAN_DIAG_SUPPORT 1145 mutex_init(&emlxs_sd_bucket_mutex, NULL, MUTEX_DRIVER, NULL); 1146 #endif /* SAN_DIAG_SUPPORT */ 1147 1148 return (ret); 1149 1150 } /* _init() */ 1151 1152 1153 /* 1154 * Called when driver is unloaded. 1155 */ 1156 int 1157 _fini(void) 1158 { 1159 int ret; 1160 1161 if ((ret = mod_remove(&emlxs_modlinkage)) != 0) { 1162 return (ret); 1163 } 1164 #ifdef MODSYM_SUPPORT 1165 /* Close SFS */ 1166 emlxs_fca_modclose(); 1167 #endif /* MODSYM_SUPPORT */ 1168 1169 /* 1170 * Destroy the soft state structure 1171 */ 1172 (void) ddi_soft_state_fini(&emlxs_soft_state); 1173 1174 /* Destroy the global device lock */ 1175 mutex_destroy(&emlxs_device.lock); 1176 1177 #ifdef SAN_DIAG_SUPPORT 1178 mutex_destroy(&emlxs_sd_bucket_mutex); 1179 #endif /* SAN_DIAG_SUPPORT */ 1180 1181 return (ret); 1182 1183 } /* _fini() */ 1184 1185 1186 1187 int 1188 _info(struct modinfo *modinfop) 1189 { 1190 1191 return (mod_info(&emlxs_modlinkage, modinfop)); 1192 1193 } /* _info() */ 1194 1195 1196 /* 1197 * Attach an ddiinst of an emlx host adapter. 1198 * Allocate data structures, initialize the adapter and we're ready to fly. 1199 */ 1200 static int 1201 emlxs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1202 { 1203 emlxs_hba_t *hba; 1204 int ddiinst; 1205 int emlxinst; 1206 int rval; 1207 1208 switch (cmd) { 1209 case DDI_ATTACH: 1210 /* If successful this will set EMLXS_PM_IN_ATTACH */ 1211 rval = emlxs_hba_attach(dip); 1212 break; 1213 1214 case DDI_RESUME: 1215 /* This will resume the driver */ 1216 rval = emlxs_hba_resume(dip); 1217 break; 1218 1219 default: 1220 rval = DDI_FAILURE; 1221 } 1222 1223 if (rval == DDI_SUCCESS) { 1224 ddiinst = ddi_get_instance(dip); 1225 emlxinst = emlxs_get_instance(ddiinst); 1226 hba = emlxs_device.hba[emlxinst]; 1227 1228 if ((hba != NULL) && (hba != (emlxs_hba_t *)-1)) { 1229 1230 /* Enable driver dump feature */ 1231 mutex_enter(&EMLXS_PORT_LOCK); 1232 hba->flag |= FC_DUMP_SAFE; 1233 mutex_exit(&EMLXS_PORT_LOCK); 1234 } 1235 } 1236 1237 return (rval); 1238 1239 } /* emlxs_attach() */ 1240 1241 1242 /* 1243 * Detach/prepare driver to unload (see detach(9E)). 1244 */ 1245 static int 1246 emlxs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1247 { 1248 emlxs_hba_t *hba; 1249 emlxs_port_t *port; 1250 int ddiinst; 1251 int emlxinst; 1252 int rval; 1253 1254 ddiinst = ddi_get_instance(dip); 1255 emlxinst = emlxs_get_instance(ddiinst); 1256 hba = emlxs_device.hba[emlxinst]; 1257 1258 if (hba == NULL) { 1259 cmn_err(CE_WARN, "?%s: Detach: NULL device.", DRIVER_NAME); 1260 1261 return (DDI_FAILURE); 1262 } 1263 1264 if (hba == (emlxs_hba_t *)-1) { 1265 cmn_err(CE_WARN, "?%s: Detach: Device attach failed.", 1266 DRIVER_NAME); 1267 1268 return (DDI_FAILURE); 1269 } 1270 1271 port = &PPORT; 1272 rval = DDI_SUCCESS; 1273 1274 /* Check driver dump */ 1275 mutex_enter(&EMLXS_PORT_LOCK); 1276 1277 if (hba->flag & FC_DUMP_ACTIVE) { 1278 mutex_exit(&EMLXS_PORT_LOCK); 1279 1280 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1281 "detach: Driver busy. Driver dump active."); 1282 1283 return (DDI_FAILURE); 1284 } 1285 1286 #ifdef SFCT_SUPPORT 1287 if ((port->flag & EMLXS_TGT_BOUND) && 1288 ((port->fct_flags & FCT_STATE_PORT_ONLINE) || 1289 (port->fct_flags & FCT_STATE_NOT_ACKED))) { 1290 mutex_exit(&EMLXS_PORT_LOCK); 1291 1292 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1293 "detach: Driver busy. Target mode active."); 1294 1295 return (DDI_FAILURE); 1296 } 1297 #endif /* SFCT_SUPPORT */ 1298 1299 if (port->flag & EMLXS_INI_BOUND) { 1300 mutex_exit(&EMLXS_PORT_LOCK); 1301 1302 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1303 "detach: Driver busy. Initiator mode active."); 1304 1305 return (DDI_FAILURE); 1306 } 1307 1308 hba->flag &= ~FC_DUMP_SAFE; 1309 1310 mutex_exit(&EMLXS_PORT_LOCK); 1311 1312 switch (cmd) { 1313 case DDI_DETACH: 1314 1315 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, 1316 "DDI_DETACH"); 1317 1318 rval = emlxs_hba_detach(dip); 1319 1320 if (rval != DDI_SUCCESS) { 1321 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1322 "Unable to detach."); 1323 } 1324 break; 1325 1326 case DDI_SUSPEND: 1327 1328 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, 1329 "DDI_SUSPEND"); 1330 1331 /* Suspend the driver */ 1332 rval = emlxs_hba_suspend(dip); 1333 1334 if (rval != DDI_SUCCESS) { 1335 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1336 "Unable to suspend driver."); 1337 } 1338 break; 1339 1340 default: 1341 cmn_err(CE_WARN, "?%s: Detach: Unknown cmd received. cmd=%x", 1342 DRIVER_NAME, cmd); 1343 rval = DDI_FAILURE; 1344 } 1345 1346 if (rval == DDI_FAILURE) { 1347 /* Re-Enable driver dump feature */ 1348 mutex_enter(&EMLXS_PORT_LOCK); 1349 hba->flag |= FC_DUMP_SAFE; 1350 mutex_exit(&EMLXS_PORT_LOCK); 1351 } 1352 1353 return (rval); 1354 1355 } /* emlxs_detach() */ 1356 1357 1358 /* EMLXS_PORT_LOCK must be held when calling this */ 1359 extern void 1360 emlxs_port_init(emlxs_port_t *port) 1361 { 1362 emlxs_hba_t *hba = HBA; 1363 1364 /* Initialize the base node */ 1365 bzero((caddr_t)&port->node_base, sizeof (NODELIST)); 1366 port->node_base.nlp_Rpi = 0; 1367 port->node_base.nlp_DID = 0xffffff; 1368 port->node_base.nlp_list_next = NULL; 1369 port->node_base.nlp_list_prev = NULL; 1370 port->node_base.nlp_active = 1; 1371 port->node_base.nlp_base = 1; 1372 port->node_count = 0; 1373 1374 if (!(port->flag & EMLXS_PORT_ENABLED)) { 1375 uint8_t dummy_wwn[8] = 1376 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 1377 1378 bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwnn, 1379 sizeof (NAME_TYPE)); 1380 bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwpn, 1381 sizeof (NAME_TYPE)); 1382 } 1383 1384 if (!(port->flag & EMLXS_PORT_CONFIG)) { 1385 (void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn, 1386 (sizeof (port->snn)-1)); 1387 (void) strncpy((caddr_t)port->spn, (caddr_t)hba->spn, 1388 (sizeof (port->spn)-1)); 1389 } 1390 1391 bcopy((caddr_t)&hba->sparam, (caddr_t)&port->sparam, 1392 sizeof (SERV_PARM)); 1393 bcopy((caddr_t)&port->wwnn, (caddr_t)&port->sparam.nodeName, 1394 sizeof (NAME_TYPE)); 1395 bcopy((caddr_t)&port->wwpn, (caddr_t)&port->sparam.portName, 1396 sizeof (NAME_TYPE)); 1397 1398 return; 1399 1400 } /* emlxs_port_init() */ 1401 1402 1403 void 1404 emlxs_disable_pcie_ce_err(emlxs_hba_t *hba) 1405 { 1406 uint16_t reg; 1407 1408 if (!hba->pci_cap_offset[PCI_CAP_ID_PCI_E]) { 1409 return; 1410 } 1411 1412 /* Turn off the Correctable Error Reporting */ 1413 /* (the Device Control Register, bit 0). */ 1414 reg = ddi_get16(hba->pci_acc_handle, 1415 (uint16_t *)(hba->pci_addr + 1416 hba->pci_cap_offset[PCI_CAP_ID_PCI_E] + 1417 PCIE_DEVCTL)); 1418 1419 reg &= ~1; 1420 1421 (void) ddi_put16(hba->pci_acc_handle, 1422 (uint16_t *)(hba->pci_addr + 1423 hba->pci_cap_offset[PCI_CAP_ID_PCI_E] + 1424 PCIE_DEVCTL), 1425 reg); 1426 1427 return; 1428 1429 } /* emlxs_disable_pcie_ce_err() */ 1430 1431 1432 /* 1433 * emlxs_fca_bind_port 1434 * 1435 * Arguments: 1436 * 1437 * dip: the dev_info pointer for the ddiinst 1438 * port_info: pointer to info handed back to the transport 1439 * bind_info: pointer to info from the transport 1440 * 1441 * Return values: a port handle for this port, NULL for failure 1442 * 1443 */ 1444 static opaque_t 1445 emlxs_fca_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, 1446 fc_fca_bind_info_t *bind_info) 1447 { 1448 emlxs_hba_t *hba; 1449 emlxs_port_t *port; 1450 emlxs_port_t *pport; 1451 emlxs_port_t *vport; 1452 int ddiinst; 1453 emlxs_vpd_t *vpd; 1454 emlxs_config_t *cfg; 1455 char *dptr; 1456 char buffer[16]; 1457 uint32_t length; 1458 uint32_t len; 1459 char topology[32]; 1460 char linkspeed[32]; 1461 uint32_t linkstate; 1462 1463 ddiinst = ddi_get_instance(dip); 1464 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 1465 port = &PPORT; 1466 pport = &PPORT; 1467 1468 ddiinst = hba->ddiinst; 1469 vpd = &VPD; 1470 cfg = &CFG; 1471 1472 mutex_enter(&EMLXS_PORT_LOCK); 1473 1474 if (bind_info->port_num > 0) { 1475 #if (EMLXS_MODREV >= EMLXS_MODREV5) 1476 if (!(hba->flag & FC_NPIV_ENABLED) || 1477 !(bind_info->port_npiv) || 1478 (bind_info->port_num > hba->vpi_max)) 1479 #elif (EMLXS_MODREV >= EMLXS_MODREV3) 1480 if (!(hba->flag & FC_NPIV_ENABLED) || 1481 (bind_info->port_num > hba->vpi_high)) 1482 #endif 1483 { 1484 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 1485 "fca_bind_port: Port %d not supported.", 1486 bind_info->port_num); 1487 1488 mutex_exit(&EMLXS_PORT_LOCK); 1489 1490 port_info->pi_error = FC_OUTOFBOUNDS; 1491 return (NULL); 1492 } 1493 } 1494 1495 /* Get true port pointer */ 1496 port = &VPORT(bind_info->port_num); 1497 1498 /* Make sure the port is not already bound to the transport */ 1499 if (port->flag & EMLXS_INI_BOUND) { 1500 1501 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 1502 "fca_bind_port: Port %d already bound. flag=%x", 1503 bind_info->port_num, port->flag); 1504 1505 mutex_exit(&EMLXS_PORT_LOCK); 1506 1507 port_info->pi_error = FC_ALREADY; 1508 return (NULL); 1509 } 1510 1511 if (!(pport->flag & EMLXS_INI_ENABLED)) { 1512 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 1513 "fca_bind_port: Physical port does not support " 1514 "initiator mode."); 1515 1516 mutex_exit(&EMLXS_PORT_LOCK); 1517 1518 port_info->pi_error = FC_OUTOFBOUNDS; 1519 return (NULL); 1520 } 1521 1522 /* Make sure port enable flag is set */ 1523 /* Just in case fca_port_unbind is called just prior to fca_port_bind */ 1524 /* without a driver attach or resume operation */ 1525 port->flag |= EMLXS_PORT_ENABLED; 1526 1527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 1528 "fca_bind_port: Port %d: port_info=%p bind_info=%p", 1529 bind_info->port_num, port_info, bind_info); 1530 1531 #if (EMLXS_MODREV >= EMLXS_MODREV5) 1532 if (bind_info->port_npiv) { 1533 /* Leadville is telling us about a new virtual port */ 1534 bcopy((caddr_t)&bind_info->port_nwwn, (caddr_t)&port->wwnn, 1535 sizeof (NAME_TYPE)); 1536 bcopy((caddr_t)&bind_info->port_pwwn, (caddr_t)&port->wwpn, 1537 sizeof (NAME_TYPE)); 1538 if (port->snn[0] == 0) { 1539 (void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn, 1540 (sizeof (port->snn)-1)); 1541 1542 } 1543 1544 if (port->spn[0] == 0) { 1545 (void) snprintf((caddr_t)port->spn, 1546 (sizeof (port->spn)-1), "%s VPort-%d", 1547 (caddr_t)hba->spn, port->vpi); 1548 } 1549 port->flag |= EMLXS_PORT_CONFIG; 1550 } 1551 #endif /* >= EMLXS_MODREV5 */ 1552 1553 /* 1554 * Restricted login should apply both physical and 1555 * virtual ports. 1556 */ 1557 if (cfg[CFG_VPORT_RESTRICTED].current) { 1558 port->flag |= EMLXS_PORT_RESTRICTED; 1559 } 1560 1561 /* Perform generic port initialization */ 1562 emlxs_port_init(port); 1563 1564 /* Perform SFS specific initialization */ 1565 port->ulp_handle = bind_info->port_handle; 1566 port->ulp_statec_cb = bind_info->port_statec_cb; 1567 port->ulp_unsol_cb = bind_info->port_unsol_cb; 1568 1569 /* Set the bound flag */ 1570 port->flag |= EMLXS_INI_BOUND; 1571 hba->num_of_ports++; 1572 1573 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1574 mutex_exit(&EMLXS_PORT_LOCK); 1575 (void) emlxs_vpi_port_bind_notify(port); 1576 mutex_enter(&EMLXS_PORT_LOCK); 1577 1578 linkstate = (port->vpip->state == VPI_STATE_PORT_ONLINE)? 1579 FC_LINK_UP:FC_LINK_DOWN; 1580 } else { 1581 linkstate = hba->state; 1582 } 1583 1584 /* Update the port info structure */ 1585 1586 /* Set the topology and state */ 1587 if (port->mode == MODE_TARGET) { 1588 port_info->pi_port_state = FC_STATE_OFFLINE; 1589 port_info->pi_topology = FC_TOP_UNKNOWN; 1590 } else if ((linkstate < FC_LINK_UP) || 1591 ((port->vpi > 0) && (!(port->flag & EMLXS_PORT_ENABLED) || 1592 !(hba->flag & FC_NPIV_SUPPORTED)))) { 1593 port_info->pi_port_state = FC_STATE_OFFLINE; 1594 port_info->pi_topology = FC_TOP_UNKNOWN; 1595 } 1596 #ifdef MENLO_SUPPORT 1597 else if (hba->flag & FC_MENLO_MODE) { 1598 port_info->pi_port_state = FC_STATE_OFFLINE; 1599 port_info->pi_topology = FC_TOP_UNKNOWN; 1600 } 1601 #endif /* MENLO_SUPPORT */ 1602 else { 1603 /* Check for loop topology */ 1604 if (hba->topology == TOPOLOGY_LOOP) { 1605 port_info->pi_port_state = FC_STATE_LOOP; 1606 (void) strlcpy(topology, ", loop", sizeof (topology)); 1607 1608 if (hba->flag & FC_FABRIC_ATTACHED) { 1609 port_info->pi_topology = FC_TOP_PUBLIC_LOOP; 1610 } else { 1611 port_info->pi_topology = FC_TOP_PRIVATE_LOOP; 1612 } 1613 } else { 1614 port_info->pi_topology = FC_TOP_FABRIC; 1615 port_info->pi_port_state = FC_STATE_ONLINE; 1616 (void) strlcpy(topology, ", fabric", sizeof (topology)); 1617 } 1618 1619 /* Set the link speed */ 1620 switch (hba->linkspeed) { 1621 case 0: 1622 (void) strlcpy(linkspeed, "Gb", sizeof (linkspeed)); 1623 port_info->pi_port_state |= FC_STATE_1GBIT_SPEED; 1624 break; 1625 1626 case LA_1GHZ_LINK: 1627 (void) strlcpy(linkspeed, "1Gb", sizeof (linkspeed)); 1628 port_info->pi_port_state |= FC_STATE_1GBIT_SPEED; 1629 break; 1630 case LA_2GHZ_LINK: 1631 (void) strlcpy(linkspeed, "2Gb", sizeof (linkspeed)); 1632 port_info->pi_port_state |= FC_STATE_2GBIT_SPEED; 1633 break; 1634 case LA_4GHZ_LINK: 1635 (void) strlcpy(linkspeed, "4Gb", sizeof (linkspeed)); 1636 port_info->pi_port_state |= FC_STATE_4GBIT_SPEED; 1637 break; 1638 case LA_8GHZ_LINK: 1639 (void) strlcpy(linkspeed, "8Gb", sizeof (linkspeed)); 1640 port_info->pi_port_state |= FC_STATE_8GBIT_SPEED; 1641 break; 1642 case LA_10GHZ_LINK: 1643 (void) strlcpy(linkspeed, "10Gb", sizeof (linkspeed)); 1644 port_info->pi_port_state |= FC_STATE_10GBIT_SPEED; 1645 break; 1646 case LA_16GHZ_LINK: 1647 (void) strlcpy(linkspeed, "16Gb", sizeof (linkspeed)); 1648 port_info->pi_port_state |= FC_STATE_16GBIT_SPEED; 1649 break; 1650 default: 1651 (void) snprintf(linkspeed, sizeof (linkspeed), 1652 "unknown(0x%x)", hba->linkspeed); 1653 break; 1654 } 1655 1656 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 1657 /* Adjusting port context for link up messages */ 1658 vport = port; 1659 port = &PPORT; 1660 if (vport->vpi == 0) { 1661 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, 1662 "%s%s, initiator", 1663 linkspeed, topology); 1664 } else if (!(hba->flag & FC_NPIV_LINKUP)) { 1665 hba->flag |= FC_NPIV_LINKUP; 1666 EMLXS_MSGF(EMLXS_CONTEXT, 1667 &emlxs_npiv_link_up_msg, 1668 "%s%s, initiator", linkspeed, topology); 1669 } 1670 port = vport; 1671 } 1672 } 1673 1674 /* PCIE Correctable Error Reporting workaround */ 1675 if (((hba->model_info.chip == EMLXS_BE2_CHIP) || 1676 (hba->model_info.chip == EMLXS_BE3_CHIP)) && 1677 (bind_info->port_num == 0)) { 1678 emlxs_disable_pcie_ce_err(hba); 1679 } 1680 1681 /* Save initial state */ 1682 port->ulp_statec = port_info->pi_port_state; 1683 1684 /* 1685 * The transport needs a copy of the common service parameters 1686 * for this port. The transport can get any updates through 1687 * the getcap entry point. 1688 */ 1689 bcopy((void *) &port->sparam, 1690 (void *) &port_info->pi_login_params.common_service, 1691 sizeof (SERV_PARM)); 1692 1693 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 1694 /* Swap the service parameters for ULP */ 1695 emlxs_swap_service_params((SERV_PARM *)&port_info->pi_login_params. 1696 common_service); 1697 #endif /* EMLXS_MODREV2X */ 1698 1699 port_info->pi_login_params.common_service.btob_credit = 0xffff; 1700 1701 bcopy((void *) &port->wwnn, 1702 (void *) &port_info->pi_login_params.node_ww_name, 1703 sizeof (NAME_TYPE)); 1704 1705 bcopy((void *) &port->wwpn, 1706 (void *) &port_info->pi_login_params.nport_ww_name, 1707 sizeof (NAME_TYPE)); 1708 1709 /* 1710 * We need to turn off CLASS2 support. 1711 * Otherwise, FC transport will use CLASS2 as default class 1712 * and never try with CLASS3. 1713 */ 1714 #if (EMLXS_MODREV >= EMLXS_MODREV3) 1715 #if (EMLXS_MODREVX >= EMLXS_MODREV3X) 1716 if ((port_info->pi_login_params.class_1.class_opt) & 0x0080) { 1717 port_info->pi_login_params.class_1.class_opt &= ~0x0080; 1718 } 1719 1720 if ((port_info->pi_login_params.class_2.class_opt) & 0x0080) { 1721 port_info->pi_login_params.class_2.class_opt &= ~0x0080; 1722 } 1723 #else /* EMLXS_SPARC or EMLXS_MODREV2X */ 1724 if ((port_info->pi_login_params.class_1.class_opt) & 0x8000) { 1725 port_info->pi_login_params.class_1.class_opt &= ~0x8000; 1726 } 1727 1728 if ((port_info->pi_login_params.class_2.class_opt) & 0x8000) { 1729 port_info->pi_login_params.class_2.class_opt &= ~0x8000; 1730 } 1731 #endif /* >= EMLXS_MODREV3X */ 1732 #endif /* >= EMLXS_MODREV3 */ 1733 1734 1735 #if (EMLXS_MODREV <= EMLXS_MODREV2) 1736 if ((port_info->pi_login_params.class_1.data[0]) & 0x80) { 1737 port_info->pi_login_params.class_1.data[0] &= ~0x80; 1738 } 1739 1740 if ((port_info->pi_login_params.class_2.data[0]) & 0x80) { 1741 port_info->pi_login_params.class_2.data[0] &= ~0x80; 1742 } 1743 #endif /* <= EMLXS_MODREV2 */ 1744 1745 /* Additional parameters */ 1746 port_info->pi_s_id.port_id = port->did; 1747 port_info->pi_s_id.priv_lilp_posit = 0; 1748 port_info->pi_hard_addr.hard_addr = cfg[CFG_ASSIGN_ALPA].current; 1749 1750 /* Initialize the RNID parameters */ 1751 bzero(&port_info->pi_rnid_params, sizeof (port_info->pi_rnid_params)); 1752 1753 (void) snprintf((char *)port_info->pi_rnid_params.params.global_id, 1754 (sizeof (port_info->pi_rnid_params.params.global_id)-1), 1755 "%01x%01x%02x%02x%02x%02x%02x%02x%02x", hba->wwpn.nameType, 1756 hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0], 1757 hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3], 1758 hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 1759 1760 port_info->pi_rnid_params.params.unit_type = RNID_HBA; 1761 port_info->pi_rnid_params.params.port_id = port->did; 1762 port_info->pi_rnid_params.params.ip_version = RNID_IPV4; 1763 1764 /* Initialize the port attributes */ 1765 bzero(&port_info->pi_attrs, sizeof (port_info->pi_attrs)); 1766 1767 (void) strncpy(port_info->pi_attrs.manufacturer, "Emulex", 1768 (sizeof (port_info->pi_attrs.manufacturer)-1)); 1769 1770 port_info->pi_rnid_params.status = FC_SUCCESS; 1771 1772 (void) strncpy(port_info->pi_attrs.serial_number, vpd->serial_num, 1773 (sizeof (port_info->pi_attrs.serial_number)-1)); 1774 1775 (void) snprintf(port_info->pi_attrs.firmware_version, 1776 (sizeof (port_info->pi_attrs.firmware_version)-1), "%s (%s)", 1777 vpd->fw_version, vpd->fw_label); 1778 1779 #ifdef EMLXS_I386 1780 (void) snprintf(port_info->pi_attrs.option_rom_version, 1781 (sizeof (port_info->pi_attrs.option_rom_version)-1), 1782 "Boot:%s", vpd->boot_version); 1783 #else /* EMLXS_SPARC */ 1784 (void) snprintf(port_info->pi_attrs.option_rom_version, 1785 (sizeof (port_info->pi_attrs.option_rom_version)-1), 1786 "Boot:%s Fcode:%s", vpd->boot_version, vpd->fcode_version); 1787 #endif /* EMLXS_I386 */ 1788 1789 (void) snprintf(port_info->pi_attrs.driver_version, 1790 (sizeof (port_info->pi_attrs.driver_version)-1), "%s (%s)", 1791 emlxs_version, emlxs_revision); 1792 1793 (void) strncpy(port_info->pi_attrs.driver_name, DRIVER_NAME, 1794 (sizeof (port_info->pi_attrs.driver_name)-1)); 1795 1796 port_info->pi_attrs.vendor_specific_id = 1797 ((hba->model_info.device_id << 16) | PCI_VENDOR_ID_EMULEX); 1798 1799 port_info->pi_attrs.supported_cos = LE_SWAP32(FC_NS_CLASS3); 1800 1801 port_info->pi_attrs.max_frame_size = FF_FRAME_SIZE; 1802 1803 #if (EMLXS_MODREV >= EMLXS_MODREV3) 1804 port_info->pi_rnid_params.params.num_attached = 0; 1805 1806 if (hba->model_info.chip == EMLXS_LANCER_CHIP) { 1807 uint8_t byte; 1808 uint8_t *wwpn; 1809 uint32_t i; 1810 uint32_t j; 1811 1812 /* Copy the WWPN as a string into the local buffer */ 1813 wwpn = (uint8_t *)&hba->wwpn; 1814 for (i = 0; i < 16; i++) { 1815 byte = *wwpn++; 1816 j = ((byte & 0xf0) >> 4); 1817 if (j <= 9) { 1818 buffer[i] = 1819 (char)((uint8_t)'0' + (uint8_t)j); 1820 } else { 1821 buffer[i] = 1822 (char)((uint8_t)'A' + (uint8_t)(j - 1823 10)); 1824 } 1825 1826 i++; 1827 j = (byte & 0xf); 1828 if (j <= 9) { 1829 buffer[i] = 1830 (char)((uint8_t)'0' + (uint8_t)j); 1831 } else { 1832 buffer[i] = 1833 (char)((uint8_t)'A' + (uint8_t)(j - 1834 10)); 1835 } 1836 } 1837 1838 port_info->pi_attrs.hba_fru_details.port_index = 0; 1839 #if ((EMLXS_MODREV == EMLXS_MODREV3) || (EMLXS_MODREV == EMLXS_MODREV4)) 1840 1841 } else if (hba->flag & FC_NPIV_ENABLED) { 1842 uint8_t byte; 1843 uint8_t *wwpn; 1844 uint32_t i; 1845 uint32_t j; 1846 1847 /* Copy the WWPN as a string into the local buffer */ 1848 wwpn = (uint8_t *)&hba->wwpn; 1849 for (i = 0; i < 16; i++) { 1850 byte = *wwpn++; 1851 j = ((byte & 0xf0) >> 4); 1852 if (j <= 9) { 1853 buffer[i] = 1854 (char)((uint8_t)'0' + (uint8_t)j); 1855 } else { 1856 buffer[i] = 1857 (char)((uint8_t)'A' + (uint8_t)(j - 1858 10)); 1859 } 1860 1861 i++; 1862 j = (byte & 0xf); 1863 if (j <= 9) { 1864 buffer[i] = 1865 (char)((uint8_t)'0' + (uint8_t)j); 1866 } else { 1867 buffer[i] = 1868 (char)((uint8_t)'A' + (uint8_t)(j - 1869 10)); 1870 } 1871 } 1872 1873 port_info->pi_attrs.hba_fru_details.port_index = port->vpi; 1874 #endif /* == EMLXS_MODREV3 || EMLXS_MODREV4 */ 1875 1876 } else { 1877 /* Copy the serial number string (right most 16 chars) */ 1878 /* into the right justified local buffer */ 1879 bzero(buffer, sizeof (buffer)); 1880 length = strlen(vpd->serial_num); 1881 len = (length > 16) ? 16 : length; 1882 bcopy(&vpd->serial_num[(length - len)], 1883 &buffer[(sizeof (buffer) - len)], len); 1884 1885 port_info->pi_attrs.hba_fru_details.port_index = 1886 vpd->port_index; 1887 } 1888 1889 dptr = (char *)&port_info->pi_attrs.hba_fru_details.high; 1890 dptr[0] = buffer[0]; 1891 dptr[1] = buffer[1]; 1892 dptr[2] = buffer[2]; 1893 dptr[3] = buffer[3]; 1894 dptr[4] = buffer[4]; 1895 dptr[5] = buffer[5]; 1896 dptr[6] = buffer[6]; 1897 dptr[7] = buffer[7]; 1898 port_info->pi_attrs.hba_fru_details.high = 1899 LE_SWAP64(port_info->pi_attrs.hba_fru_details.high); 1900 1901 dptr = (char *)&port_info->pi_attrs.hba_fru_details.low; 1902 dptr[0] = buffer[8]; 1903 dptr[1] = buffer[9]; 1904 dptr[2] = buffer[10]; 1905 dptr[3] = buffer[11]; 1906 dptr[4] = buffer[12]; 1907 dptr[5] = buffer[13]; 1908 dptr[6] = buffer[14]; 1909 dptr[7] = buffer[15]; 1910 port_info->pi_attrs.hba_fru_details.low = 1911 LE_SWAP64(port_info->pi_attrs.hba_fru_details.low); 1912 1913 #endif /* >= EMLXS_MODREV3 */ 1914 1915 #if (EMLXS_MODREV >= EMLXS_MODREV4) 1916 (void) strncpy((caddr_t)port_info->pi_attrs.sym_node_name, 1917 (caddr_t)port->snn, FCHBA_SYMB_NAME_LEN); 1918 (void) strncpy((caddr_t)port_info->pi_attrs.sym_port_name, 1919 (caddr_t)port->spn, FCHBA_SYMB_NAME_LEN); 1920 #endif /* >= EMLXS_MODREV4 */ 1921 1922 (void) snprintf(port_info->pi_attrs.hardware_version, 1923 (sizeof (port_info->pi_attrs.hardware_version)-1), 1924 "%x", vpd->biuRev); 1925 1926 /* Set the hba speed limit */ 1927 if (vpd->link_speed & LMT_16GB_CAPABLE) { 1928 port_info->pi_attrs.supported_speed |= 1929 FC_HBA_PORTSPEED_16GBIT; 1930 } 1931 if (vpd->link_speed & LMT_10GB_CAPABLE) { 1932 port_info->pi_attrs.supported_speed |= 1933 FC_HBA_PORTSPEED_10GBIT; 1934 } 1935 if (vpd->link_speed & LMT_8GB_CAPABLE) { 1936 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_8GBIT; 1937 } 1938 if (vpd->link_speed & LMT_4GB_CAPABLE) { 1939 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_4GBIT; 1940 } 1941 if (vpd->link_speed & LMT_2GB_CAPABLE) { 1942 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_2GBIT; 1943 } 1944 if (vpd->link_speed & LMT_1GB_CAPABLE) { 1945 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_1GBIT; 1946 } 1947 1948 /* Set the hba model info */ 1949 (void) strncpy(port_info->pi_attrs.model, hba->model_info.model, 1950 (sizeof (port_info->pi_attrs.model)-1)); 1951 (void) strncpy(port_info->pi_attrs.model_description, 1952 hba->model_info.model_desc, 1953 (sizeof (port_info->pi_attrs.model_description)-1)); 1954 1955 1956 /* Log information */ 1957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1958 "Bind info: port_num = %d", bind_info->port_num); 1959 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1960 "Bind info: port_handle = %p", bind_info->port_handle); 1961 1962 #if (EMLXS_MODREV >= EMLXS_MODREV5) 1963 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1964 "Bind info: port_npiv = %d", bind_info->port_npiv); 1965 #endif /* >= EMLXS_MODREV5 */ 1966 1967 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1968 "Port info: pi_topology = %x", port_info->pi_topology); 1969 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1970 "Port info: pi_error = %x", port_info->pi_error); 1971 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1972 "Port info: pi_port_state = %x", port_info->pi_port_state); 1973 1974 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1975 "Port info: port_id = %x", port_info->pi_s_id.port_id); 1976 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1977 "Port info: priv_lilp_posit = %x", 1978 port_info->pi_s_id.priv_lilp_posit); 1979 1980 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1981 "Port info: hard_addr = %x", 1982 port_info->pi_hard_addr.hard_addr); 1983 1984 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1985 "Port info: rnid.status = %x", 1986 port_info->pi_rnid_params.status); 1987 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1988 "Port info: rnid.global_id = %16s", 1989 port_info->pi_rnid_params.params.global_id); 1990 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1991 "Port info: rnid.unit_type = %x", 1992 port_info->pi_rnid_params.params.unit_type); 1993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1994 "Port info: rnid.port_id = %x", 1995 port_info->pi_rnid_params.params.port_id); 1996 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1997 "Port info: rnid.num_attached = %x", 1998 port_info->pi_rnid_params.params.num_attached); 1999 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2000 "Port info: rnid.ip_version = %x", 2001 port_info->pi_rnid_params.params.ip_version); 2002 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2003 "Port info: rnid.udp_port = %x", 2004 port_info->pi_rnid_params.params.udp_port); 2005 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2006 "Port info: rnid.ip_addr = %16s", 2007 port_info->pi_rnid_params.params.ip_addr); 2008 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2009 "Port info: rnid.spec_id_resv = %x", 2010 port_info->pi_rnid_params.params.specific_id_resv); 2011 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2012 "Port info: rnid.topo_flags = %x", 2013 port_info->pi_rnid_params.params.topo_flags); 2014 2015 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2016 "Port info: manufacturer = %s", 2017 port_info->pi_attrs.manufacturer); 2018 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2019 "Port info: serial_num = %s", 2020 port_info->pi_attrs.serial_number); 2021 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2022 "Port info: model = %s", port_info->pi_attrs.model); 2023 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2024 "Port info: model_description = %s", 2025 port_info->pi_attrs.model_description); 2026 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2027 "Port info: hardware_version = %s", 2028 port_info->pi_attrs.hardware_version); 2029 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2030 "Port info: driver_version = %s", 2031 port_info->pi_attrs.driver_version); 2032 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2033 "Port info: option_rom_version = %s", 2034 port_info->pi_attrs.option_rom_version); 2035 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2036 "Port info: firmware_version = %s", 2037 port_info->pi_attrs.firmware_version); 2038 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2039 "Port info: driver_name = %s", 2040 port_info->pi_attrs.driver_name); 2041 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2042 "Port info: vendor_specific_id = %x", 2043 port_info->pi_attrs.vendor_specific_id); 2044 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2045 "Port info: supported_cos = %x", 2046 port_info->pi_attrs.supported_cos); 2047 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2048 "Port info: supported_speed = %x", 2049 port_info->pi_attrs.supported_speed); 2050 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2051 "Port info: max_frame_size = %x", 2052 port_info->pi_attrs.max_frame_size); 2053 2054 #if (EMLXS_MODREV >= EMLXS_MODREV3) 2055 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2056 "Port info: fru_port_index = %x", 2057 port_info->pi_attrs.hba_fru_details.port_index); 2058 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2059 "Port info: fru_high = %llx", 2060 port_info->pi_attrs.hba_fru_details.high); 2061 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2062 "Port info: fru_low = %llx", 2063 port_info->pi_attrs.hba_fru_details.low); 2064 #endif /* >= EMLXS_MODREV3 */ 2065 2066 #if (EMLXS_MODREV >= EMLXS_MODREV4) 2067 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2068 "Port info: sym_node_name = %s", 2069 port_info->pi_attrs.sym_node_name); 2070 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2071 "Port info: sym_port_name = %s", 2072 port_info->pi_attrs.sym_port_name); 2073 #endif /* >= EMLXS_MODREV4 */ 2074 2075 mutex_exit(&EMLXS_PORT_LOCK); 2076 2077 #ifdef SFCT_SUPPORT 2078 if (port->flag & EMLXS_TGT_ENABLED) { 2079 emlxs_fct_bind_port(port); 2080 } 2081 #endif /* SFCT_SUPPORT */ 2082 2083 return ((opaque_t)port); 2084 2085 } /* emlxs_fca_bind_port() */ 2086 2087 2088 static void 2089 emlxs_fca_unbind_port(opaque_t fca_port_handle) 2090 { 2091 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2092 emlxs_hba_t *hba = HBA; 2093 2094 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2095 "fca_unbind_port: port=%p", port); 2096 2097 if (!(port->flag & EMLXS_PORT_BOUND)) { 2098 return; 2099 } 2100 2101 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2102 (void) emlxs_vpi_port_unbind_notify(port, 1); 2103 } 2104 2105 /* Destroy & flush all port nodes, if they exist */ 2106 if (port->node_count) { 2107 (void) EMLXS_SLI_UNREG_NODE(port, 0, 0, 0, 0); 2108 } 2109 2110 #if (EMLXS_MODREV >= EMLXS_MODREV5) 2111 if ((hba->sli_mode <= EMLXS_HBA_SLI3_MODE) && 2112 (hba->flag & FC_NPIV_ENABLED) && 2113 (port->flag & (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED))) { 2114 (void) emlxs_mb_unreg_vpi(port); 2115 } 2116 #endif 2117 2118 mutex_enter(&EMLXS_PORT_LOCK); 2119 if (port->flag & EMLXS_INI_BOUND) { 2120 #if (EMLXS_MODREV >= EMLXS_MODREV5) 2121 port->flag &= ~(EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED); 2122 #endif 2123 port->flag &= ~EMLXS_INI_BOUND; 2124 hba->num_of_ports--; 2125 2126 /* Wait until ulp callback interface is idle */ 2127 while (port->ulp_busy) { 2128 mutex_exit(&EMLXS_PORT_LOCK); 2129 delay(drv_usectohz(500000)); 2130 mutex_enter(&EMLXS_PORT_LOCK); 2131 } 2132 2133 port->ulp_handle = 0; 2134 port->ulp_statec = FC_STATE_OFFLINE; 2135 port->ulp_statec_cb = NULL; 2136 port->ulp_unsol_cb = NULL; 2137 } 2138 mutex_exit(&EMLXS_PORT_LOCK); 2139 2140 #ifdef SFCT_SUPPORT 2141 /* Check if port was target bound */ 2142 if (port->flag & EMLXS_TGT_BOUND) { 2143 emlxs_fct_unbind_port(port); 2144 } 2145 #endif /* SFCT_SUPPORT */ 2146 2147 return; 2148 2149 } /* emlxs_fca_unbind_port() */ 2150 2151 2152 /*ARGSUSED*/ 2153 extern int 2154 emlxs_fca_pkt_init(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) 2155 { 2156 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2157 emlxs_hba_t *hba = HBA; 2158 emlxs_buf_t *sbp = (emlxs_buf_t *)pkt->pkt_fca_private; 2159 2160 if (!sbp) { 2161 return (FC_FAILURE); 2162 } 2163 bzero((void *)sbp, sizeof (emlxs_buf_t)); 2164 2165 mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, DDI_INTR_PRI(hba->intr_arg)); 2166 sbp->pkt_flags = 2167 PACKET_VALID | PACKET_ULP_OWNED; 2168 sbp->port = port; 2169 sbp->pkt = pkt; 2170 sbp->iocbq.sbp = sbp; 2171 2172 return (FC_SUCCESS); 2173 2174 } /* emlxs_fca_pkt_init() */ 2175 2176 2177 2178 static void 2179 emlxs_initialize_pkt(emlxs_port_t *port, emlxs_buf_t *sbp) 2180 { 2181 emlxs_hba_t *hba = HBA; 2182 emlxs_config_t *cfg = &CFG; 2183 fc_packet_t *pkt = PRIV2PKT(sbp); 2184 2185 mutex_enter(&sbp->mtx); 2186 2187 /* Reinitialize */ 2188 sbp->pkt = pkt; 2189 sbp->port = port; 2190 sbp->bmp = NULL; 2191 sbp->pkt_flags &= (PACKET_VALID | PACKET_ALLOCATED); 2192 sbp->iotag = 0; 2193 sbp->ticks = 0; 2194 sbp->abort_attempts = 0; 2195 sbp->fpkt = NULL; 2196 sbp->flush_count = 0; 2197 sbp->next = NULL; 2198 2199 if (port->mode == MODE_INITIATOR) { 2200 sbp->node = NULL; 2201 sbp->did = 0; 2202 sbp->lun = EMLXS_LUN_NONE; 2203 sbp->class = 0; 2204 sbp->channel = NULL; 2205 } 2206 2207 bzero((void *)&sbp->iocbq, sizeof (IOCBQ)); 2208 sbp->iocbq.sbp = sbp; 2209 2210 if ((pkt->pkt_tran_flags & FC_TRAN_NO_INTR) || !pkt->pkt_comp || 2211 ddi_in_panic()) { 2212 sbp->pkt_flags |= PACKET_POLLED; 2213 } 2214 2215 /* Prepare the fc packet */ 2216 pkt->pkt_state = FC_PKT_SUCCESS; 2217 pkt->pkt_reason = 0; 2218 pkt->pkt_action = 0; 2219 pkt->pkt_expln = 0; 2220 pkt->pkt_data_resid = 0; 2221 pkt->pkt_resp_resid = 0; 2222 2223 /* Make sure all pkt's have a proper timeout */ 2224 if (!cfg[CFG_TIMEOUT_ENABLE].current) { 2225 /* This disables all IOCB on chip timeouts */ 2226 pkt->pkt_timeout = 0x80000000; 2227 } else if (pkt->pkt_timeout == 0 || pkt->pkt_timeout == 0xffffffff) { 2228 pkt->pkt_timeout = 60; 2229 } 2230 2231 /* Clear the response buffer */ 2232 if (pkt->pkt_rsplen) { 2233 bzero(pkt->pkt_resp, pkt->pkt_rsplen); 2234 } 2235 2236 mutex_exit(&sbp->mtx); 2237 2238 return; 2239 2240 } /* emlxs_initialize_pkt() */ 2241 2242 2243 2244 /* 2245 * We may not need this routine 2246 */ 2247 /*ARGSUSED*/ 2248 extern int 2249 emlxs_fca_pkt_uninit(opaque_t fca_port_handle, fc_packet_t *pkt) 2250 { 2251 emlxs_buf_t *sbp = PKT2PRIV(pkt); 2252 2253 if (!sbp) { 2254 return (FC_FAILURE); 2255 } 2256 2257 if (!(sbp->pkt_flags & PACKET_VALID)) { 2258 return (FC_FAILURE); 2259 } 2260 sbp->pkt_flags &= ~PACKET_VALID; 2261 mutex_destroy(&sbp->mtx); 2262 2263 return (FC_SUCCESS); 2264 2265 } /* emlxs_fca_pkt_uninit() */ 2266 2267 2268 static int 2269 emlxs_fca_get_cap(opaque_t fca_port_handle, char *cap, void *ptr) 2270 { 2271 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2272 emlxs_hba_t *hba = HBA; 2273 int32_t rval; 2274 emlxs_config_t *cfg = &CFG; 2275 2276 if (!(port->flag & EMLXS_INI_BOUND)) { 2277 return (FC_CAP_ERROR); 2278 } 2279 2280 if (strcmp(cap, FC_NODE_WWN) == 0) { 2281 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2282 "fca_get_cap: FC_NODE_WWN"); 2283 2284 bcopy((void *)&hba->wwnn, (void *)ptr, sizeof (NAME_TYPE)); 2285 rval = FC_CAP_FOUND; 2286 2287 } else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) { 2288 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2289 "fca_get_cap: FC_LOGIN_PARAMS"); 2290 2291 /* 2292 * We need to turn off CLASS2 support. 2293 * Otherwise, FC transport will use CLASS2 as default class 2294 * and never try with CLASS3. 2295 */ 2296 hba->sparam.cls2.classValid = 0; 2297 2298 bcopy((void *)&hba->sparam, (void *)ptr, sizeof (SERV_PARM)); 2299 2300 rval = FC_CAP_FOUND; 2301 2302 } else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) { 2303 int32_t *num_bufs; 2304 2305 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2306 "fca_get_cap: FC_CAP_UNSOL_BUF (%d)", 2307 cfg[CFG_UB_BUFS].current); 2308 2309 num_bufs = (int32_t *)ptr; 2310 2311 /* We multiply by MAX_VPORTS because ULP uses a */ 2312 /* formula to calculate ub bufs from this */ 2313 *num_bufs = (cfg[CFG_UB_BUFS].current * MAX_VPORTS); 2314 2315 rval = FC_CAP_FOUND; 2316 2317 } else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) { 2318 int32_t *size; 2319 2320 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2321 "fca_get_cap: FC_CAP_PAYLOAD_SIZE"); 2322 2323 size = (int32_t *)ptr; 2324 *size = -1; 2325 rval = FC_CAP_FOUND; 2326 2327 } else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) { 2328 fc_reset_action_t *action; 2329 2330 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2331 "fca_get_cap: FC_CAP_POST_RESET_BEHAVIOR"); 2332 2333 action = (fc_reset_action_t *)ptr; 2334 *action = FC_RESET_RETURN_ALL; 2335 rval = FC_CAP_FOUND; 2336 2337 } else if (strcmp(cap, FC_CAP_NOSTREAM_ON_UNALIGN_BUF) == 0) { 2338 fc_dma_behavior_t *behavior; 2339 2340 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2341 "fca_get_cap: FC_CAP_NOSTREAM_ON_UNALIGN_BUF"); 2342 2343 behavior = (fc_dma_behavior_t *)ptr; 2344 *behavior = FC_ALLOW_STREAMING; 2345 rval = FC_CAP_FOUND; 2346 2347 } else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) { 2348 fc_fcp_dma_t *fcp_dma; 2349 2350 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2351 "fca_get_cap: FC_CAP_FCP_DMA"); 2352 2353 fcp_dma = (fc_fcp_dma_t *)ptr; 2354 *fcp_dma = FC_DVMA_SPACE; 2355 rval = FC_CAP_FOUND; 2356 2357 } else { 2358 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2359 "fca_get_cap: Unknown capability. [%s]", cap); 2360 2361 rval = FC_CAP_ERROR; 2362 2363 } 2364 2365 return (rval); 2366 2367 } /* emlxs_fca_get_cap() */ 2368 2369 2370 2371 static int 2372 emlxs_fca_set_cap(opaque_t fca_port_handle, char *cap, void *ptr) 2373 { 2374 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2375 2376 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2377 "fca_set_cap: cap=[%s] arg=%p", cap, ptr); 2378 2379 return (FC_CAP_ERROR); 2380 2381 } /* emlxs_fca_set_cap() */ 2382 2383 2384 static opaque_t 2385 emlxs_fca_get_device(opaque_t fca_port_handle, fc_portid_t d_id) 2386 { 2387 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2388 2389 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2390 "fca_get_device: did=%x", d_id.port_id); 2391 2392 return (NULL); 2393 2394 } /* emlxs_fca_get_device() */ 2395 2396 2397 static int32_t 2398 emlxs_fca_notify(opaque_t fca_port_handle, uint32_t cmd) 2399 { 2400 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2401 2402 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, "fca_notify: cmd=%x", 2403 cmd); 2404 2405 return (FC_SUCCESS); 2406 2407 } /* emlxs_fca_notify */ 2408 2409 2410 2411 static int 2412 emlxs_fca_get_map(opaque_t fca_port_handle, fc_lilpmap_t *mapbuf) 2413 { 2414 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2415 emlxs_hba_t *hba = HBA; 2416 uint32_t lilp_length; 2417 2418 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2419 "fca_get_map: mapbuf=%p length=%d (%X,%X,%X,%X)", mapbuf, 2420 port->alpa_map[0], port->alpa_map[1], port->alpa_map[2], 2421 port->alpa_map[3], port->alpa_map[4]); 2422 2423 if (!(port->flag & EMLXS_INI_BOUND)) { 2424 return (FC_NOMAP); 2425 } 2426 2427 if (hba->topology != TOPOLOGY_LOOP) { 2428 return (FC_NOMAP); 2429 } 2430 2431 /* Check if alpa map is available */ 2432 if (port->alpa_map[0] != 0) { 2433 mapbuf->lilp_magic = MAGIC_LILP; 2434 } else { /* No LILP map available */ 2435 2436 /* Set lilp_magic to MAGIC_LISA and this will */ 2437 /* trigger an ALPA scan in ULP */ 2438 mapbuf->lilp_magic = MAGIC_LISA; 2439 } 2440 2441 mapbuf->lilp_myalpa = port->did; 2442 2443 /* The first byte of the alpa_map is the lilp map length */ 2444 /* Add one to include the lilp length byte itself */ 2445 lilp_length = (uint32_t)port->alpa_map[0] + 1; 2446 2447 /* Make sure the max transfer is 128 bytes */ 2448 if (lilp_length > 128) { 2449 lilp_length = 128; 2450 } 2451 2452 /* We start copying from the lilp_length field */ 2453 /* in order to get a word aligned address */ 2454 bcopy((void *)&port->alpa_map, (void *)&mapbuf->lilp_length, 2455 lilp_length); 2456 2457 return (FC_SUCCESS); 2458 2459 } /* emlxs_fca_get_map() */ 2460 2461 2462 2463 extern int 2464 emlxs_fca_transport(opaque_t fca_port_handle, fc_packet_t *pkt) 2465 { 2466 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2467 emlxs_hba_t *hba = HBA; 2468 emlxs_buf_t *sbp; 2469 uint32_t rval; 2470 uint32_t pkt_flags; 2471 2472 /* Validate packet */ 2473 sbp = PKT2PRIV(pkt); 2474 2475 /* Make sure adapter is online */ 2476 if (!(hba->flag & FC_ONLINE_MODE) && 2477 !(sbp->pkt_flags & PACKET_ALLOCATED)) { 2478 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 2479 "Adapter offline."); 2480 2481 rval = (hba->flag & FC_ONLINING_MODE) ? 2482 FC_TRAN_BUSY : FC_OFFLINE; 2483 return (rval); 2484 } 2485 2486 /* Make sure ULP was told that the port was online */ 2487 if ((port->ulp_statec == FC_STATE_OFFLINE) && 2488 !(sbp->pkt_flags & PACKET_ALLOCATED)) { 2489 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 2490 "Port offline."); 2491 2492 return (FC_OFFLINE); 2493 } 2494 2495 if (sbp->port != port) { 2496 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 2497 "Invalid port handle. sbp=%p port=%p flags=%x", sbp, 2498 sbp->port, sbp->pkt_flags); 2499 return (FC_BADPACKET); 2500 } 2501 2502 if (!(sbp->pkt_flags & (PACKET_VALID | PACKET_ULP_OWNED))) { 2503 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 2504 "Invalid packet flags. sbp=%p port=%p flags=%x", sbp, 2505 sbp->port, sbp->pkt_flags); 2506 return (FC_BADPACKET); 2507 } 2508 2509 #ifdef SFCT_SUPPORT 2510 if ((port->mode == MODE_TARGET) && !sbp->fct_cmd && 2511 !(sbp->pkt_flags & PACKET_ALLOCATED)) { 2512 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 2513 "Packet blocked. Target mode."); 2514 return (FC_TRANSPORT_ERROR); 2515 } 2516 #endif /* SFCT_SUPPORT */ 2517 2518 #ifdef IDLE_TIMER 2519 emlxs_pm_busy_component(hba); 2520 #endif /* IDLE_TIMER */ 2521 2522 /* Prepare the packet for transport */ 2523 emlxs_initialize_pkt(port, sbp); 2524 2525 /* Save a copy of the pkt flags. */ 2526 /* We will check the polling flag later */ 2527 pkt_flags = sbp->pkt_flags; 2528 2529 /* Send the packet */ 2530 switch (pkt->pkt_tran_type) { 2531 case FC_PKT_FCP_READ: 2532 case FC_PKT_FCP_WRITE: 2533 rval = emlxs_send_fcp_cmd(port, sbp, &pkt_flags); 2534 break; 2535 2536 case FC_PKT_IP_WRITE: 2537 case FC_PKT_BROADCAST: 2538 rval = emlxs_send_ip(port, sbp); 2539 break; 2540 2541 case FC_PKT_EXCHANGE: 2542 switch (pkt->pkt_cmd_fhdr.type) { 2543 case FC_TYPE_SCSI_FCP: 2544 rval = emlxs_send_fcp_cmd(port, sbp, &pkt_flags); 2545 break; 2546 2547 case FC_TYPE_FC_SERVICES: 2548 rval = emlxs_send_ct(port, sbp); 2549 break; 2550 2551 #ifdef MENLO_SUPPORT 2552 case EMLXS_MENLO_TYPE: 2553 rval = emlxs_send_menlo(port, sbp); 2554 break; 2555 #endif /* MENLO_SUPPORT */ 2556 2557 default: 2558 rval = emlxs_send_els(port, sbp); 2559 } 2560 break; 2561 2562 case FC_PKT_OUTBOUND: 2563 switch (pkt->pkt_cmd_fhdr.type) { 2564 #ifdef SFCT_SUPPORT 2565 case FC_TYPE_SCSI_FCP: 2566 rval = emlxs_send_fct_status(port, sbp); 2567 break; 2568 2569 case FC_TYPE_BASIC_LS: 2570 rval = emlxs_send_fct_abort(port, sbp); 2571 break; 2572 #endif /* SFCT_SUPPORT */ 2573 2574 case FC_TYPE_FC_SERVICES: 2575 rval = emlxs_send_ct_rsp(port, sbp); 2576 break; 2577 #ifdef MENLO_SUPPORT 2578 case EMLXS_MENLO_TYPE: 2579 rval = emlxs_send_menlo(port, sbp); 2580 break; 2581 #endif /* MENLO_SUPPORT */ 2582 2583 default: 2584 rval = emlxs_send_els_rsp(port, sbp); 2585 } 2586 break; 2587 2588 default: 2589 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 2590 "Unsupported pkt_tran_type. type=%x", pkt->pkt_tran_type); 2591 rval = FC_TRANSPORT_ERROR; 2592 break; 2593 } 2594 2595 /* Check if send was not successful */ 2596 if (rval != FC_SUCCESS) { 2597 /* Return packet to ULP */ 2598 mutex_enter(&sbp->mtx); 2599 sbp->pkt_flags |= PACKET_ULP_OWNED; 2600 mutex_exit(&sbp->mtx); 2601 2602 return (rval); 2603 } 2604 2605 /* Check if this packet should be polled for completion before */ 2606 /* returning. This check must be done with a saved copy of the */ 2607 /* pkt_flags because the packet itself could already be freed from */ 2608 /* memory if it was not polled. */ 2609 if (pkt_flags & PACKET_POLLED) { 2610 emlxs_poll(port, sbp); 2611 } 2612 2613 return (FC_SUCCESS); 2614 2615 } /* emlxs_fca_transport() */ 2616 2617 2618 2619 static void 2620 emlxs_poll(emlxs_port_t *port, emlxs_buf_t *sbp) 2621 { 2622 emlxs_hba_t *hba = HBA; 2623 fc_packet_t *pkt = PRIV2PKT(sbp); 2624 clock_t timeout; 2625 clock_t time; 2626 CHANNEL *cp; 2627 int in_panic = 0; 2628 2629 mutex_enter(&EMLXS_PORT_LOCK); 2630 hba->io_poll_count++; 2631 mutex_exit(&EMLXS_PORT_LOCK); 2632 2633 /* Check for panic situation */ 2634 cp = (CHANNEL *)sbp->channel; 2635 2636 if (ddi_in_panic()) { 2637 in_panic = 1; 2638 /* 2639 * In panic situations there will be one thread with 2640 * no interrrupts (hard or soft) and no timers 2641 */ 2642 2643 /* 2644 * We must manually poll everything in this thread 2645 * to keep the driver going. 2646 */ 2647 2648 /* Keep polling the chip until our IO is completed */ 2649 /* Driver's timer will not function during panics. */ 2650 /* Therefore, timer checks must be performed manually. */ 2651 (void) drv_getparm(LBOLT, &time); 2652 timeout = time + drv_usectohz(1000000); 2653 while (!(sbp->pkt_flags & PACKET_COMPLETED)) { 2654 EMLXS_SLI_POLL_INTR(hba); 2655 (void) drv_getparm(LBOLT, &time); 2656 2657 /* Trigger timer checks periodically */ 2658 if (time >= timeout) { 2659 emlxs_timer_checks(hba); 2660 timeout = time + drv_usectohz(1000000); 2661 } 2662 } 2663 } else { 2664 /* Wait for IO completion */ 2665 /* The driver's timer will detect */ 2666 /* any timeout and abort the I/O. */ 2667 mutex_enter(&EMLXS_PKT_LOCK); 2668 while (!(sbp->pkt_flags & PACKET_COMPLETED)) { 2669 cv_wait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK); 2670 } 2671 mutex_exit(&EMLXS_PKT_LOCK); 2672 } 2673 2674 /* Check for fcp reset pkt */ 2675 if (sbp->pkt_flags & PACKET_FCP_RESET) { 2676 if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) { 2677 /* Flush the IO's on the chipq */ 2678 (void) emlxs_chipq_node_flush(port, 2679 &hba->chan[hba->channel_fcp], 2680 sbp->node, sbp); 2681 } else { 2682 /* Flush the IO's on the chipq for this lun */ 2683 (void) emlxs_chipq_lun_flush(port, 2684 sbp->node, sbp->lun, sbp); 2685 } 2686 2687 if (sbp->flush_count == 0) { 2688 emlxs_node_open(port, sbp->node, hba->channel_fcp); 2689 goto done; 2690 } 2691 2692 /* Set the timeout so the flush has time to complete */ 2693 timeout = emlxs_timeout(hba, 60); 2694 (void) drv_getparm(LBOLT, &time); 2695 while ((time < timeout) && sbp->flush_count > 0) { 2696 delay(drv_usectohz(500000)); 2697 (void) drv_getparm(LBOLT, &time); 2698 } 2699 2700 if (sbp->flush_count == 0) { 2701 emlxs_node_open(port, sbp->node, hba->channel_fcp); 2702 goto done; 2703 } 2704 2705 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg, 2706 "sbp=%p flush_count=%d. Waiting...", sbp, 2707 sbp->flush_count); 2708 2709 /* Let's try this one more time */ 2710 2711 if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) { 2712 /* Flush the IO's on the chipq */ 2713 (void) emlxs_chipq_node_flush(port, 2714 &hba->chan[hba->channel_fcp], 2715 sbp->node, sbp); 2716 } else { 2717 /* Flush the IO's on the chipq for this lun */ 2718 (void) emlxs_chipq_lun_flush(port, 2719 sbp->node, sbp->lun, sbp); 2720 } 2721 2722 /* Reset the timeout so the flush has time to complete */ 2723 timeout = emlxs_timeout(hba, 60); 2724 (void) drv_getparm(LBOLT, &time); 2725 while ((time < timeout) && sbp->flush_count > 0) { 2726 delay(drv_usectohz(500000)); 2727 (void) drv_getparm(LBOLT, &time); 2728 } 2729 2730 if (sbp->flush_count == 0) { 2731 emlxs_node_open(port, sbp->node, hba->channel_fcp); 2732 goto done; 2733 } 2734 2735 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg, 2736 "sbp=%p flush_count=%d. Resetting link.", sbp, 2737 sbp->flush_count); 2738 2739 /* Let's first try to reset the link */ 2740 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 2741 2742 if (sbp->flush_count == 0) { 2743 goto done; 2744 } 2745 2746 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg, 2747 "sbp=%p flush_count=%d. Resetting HBA.", sbp, 2748 sbp->flush_count); 2749 2750 /* If that doesn't work, reset the adapter */ 2751 (void) emlxs_reset(port, FC_FCA_RESET); 2752 2753 if (sbp->flush_count != 0) { 2754 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg, 2755 "sbp=%p flush_count=%d. Giving up.", sbp, 2756 sbp->flush_count); 2757 } 2758 2759 } 2760 /* PACKET_FCP_RESET */ 2761 done: 2762 2763 /* Packet has been declared completed and is now ready to be returned */ 2764 2765 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 2766 emlxs_unswap_pkt(sbp); 2767 #endif /* EMLXS_MODREV2X */ 2768 2769 mutex_enter(&sbp->mtx); 2770 sbp->pkt_flags |= PACKET_ULP_OWNED; 2771 mutex_exit(&sbp->mtx); 2772 2773 mutex_enter(&EMLXS_PORT_LOCK); 2774 hba->io_poll_count--; 2775 mutex_exit(&EMLXS_PORT_LOCK); 2776 2777 #ifdef FMA_SUPPORT 2778 if (!in_panic) { 2779 emlxs_check_dma(hba, sbp); 2780 } 2781 #endif 2782 2783 /* Make ULP completion callback if required */ 2784 if (pkt->pkt_comp) { 2785 cp->ulpCmplCmd++; 2786 (*pkt->pkt_comp) (pkt); 2787 } 2788 2789 #ifdef FMA_SUPPORT 2790 if (hba->flag & FC_DMA_CHECK_ERROR) { 2791 emlxs_thread_spawn(hba, emlxs_restart_thread, 2792 NULL, NULL); 2793 } 2794 #endif 2795 2796 return; 2797 2798 } /* emlxs_poll() */ 2799 2800 2801 static int 2802 emlxs_fca_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, 2803 uint32_t *count, uint32_t type) 2804 { 2805 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2806 emlxs_hba_t *hba = HBA; 2807 char *err = NULL; 2808 emlxs_unsol_buf_t *pool = NULL; 2809 emlxs_unsol_buf_t *new_pool = NULL; 2810 emlxs_config_t *cfg = &CFG; 2811 int32_t i; 2812 int result; 2813 uint32_t free_resv; 2814 uint32_t free; 2815 fc_unsol_buf_t *ubp; 2816 emlxs_ub_priv_t *ub_priv; 2817 int rc; 2818 2819 if (!(port->flag & EMLXS_INI_ENABLED)) { 2820 if (tokens && count) { 2821 bzero(tokens, (sizeof (uint64_t) * (*count))); 2822 } 2823 return (FC_SUCCESS); 2824 } 2825 2826 if (!(port->flag & EMLXS_INI_BOUND)) { 2827 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2828 "fca_ub_alloc failed: Port not bound! size=%x count=%d " 2829 "type=%x", size, *count, type); 2830 2831 return (FC_FAILURE); 2832 } 2833 2834 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2835 "fca_ub_alloc: size=%x count=%d type=%x", size, *count, type); 2836 2837 if (count && (*count > EMLXS_MAX_UBUFS)) { 2838 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 2839 "fca_ub_alloc failed: Too many unsolicted buffers " 2840 "requested. count=%x", *count); 2841 2842 return (FC_FAILURE); 2843 2844 } 2845 2846 if (tokens == NULL) { 2847 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 2848 "fca_ub_alloc failed: Token array is NULL."); 2849 2850 return (FC_FAILURE); 2851 } 2852 2853 /* Clear the token array */ 2854 bzero(tokens, (sizeof (uint64_t) * (*count))); 2855 2856 free_resv = 0; 2857 free = *count; 2858 switch (type) { 2859 case FC_TYPE_BASIC_LS: 2860 err = "BASIC_LS"; 2861 break; 2862 case FC_TYPE_EXTENDED_LS: 2863 err = "EXTENDED_LS"; 2864 free = *count / 2; /* Hold 50% for normal use */ 2865 free_resv = *count - free; /* Reserve 50% for RSCN use */ 2866 break; 2867 case FC_TYPE_IS8802: 2868 err = "IS8802"; 2869 break; 2870 case FC_TYPE_IS8802_SNAP: 2871 err = "IS8802_SNAP"; 2872 2873 if (cfg[CFG_NETWORK_ON].current == 0) { 2874 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2875 "fca_ub_alloc failed: IP support is disabled."); 2876 2877 return (FC_FAILURE); 2878 } 2879 break; 2880 case FC_TYPE_SCSI_FCP: 2881 err = "SCSI_FCP"; 2882 break; 2883 case FC_TYPE_SCSI_GPP: 2884 err = "SCSI_GPP"; 2885 break; 2886 case FC_TYPE_HIPP_FP: 2887 err = "HIPP_FP"; 2888 break; 2889 case FC_TYPE_IPI3_MASTER: 2890 err = "IPI3_MASTER"; 2891 break; 2892 case FC_TYPE_IPI3_SLAVE: 2893 err = "IPI3_SLAVE"; 2894 break; 2895 case FC_TYPE_IPI3_PEER: 2896 err = "IPI3_PEER"; 2897 break; 2898 case FC_TYPE_FC_SERVICES: 2899 err = "FC_SERVICES"; 2900 break; 2901 } 2902 2903 mutex_enter(&EMLXS_UB_LOCK); 2904 2905 /* 2906 * Walk through the list of the unsolicited buffers 2907 * for this ddiinst of emlx. 2908 */ 2909 2910 pool = port->ub_pool; 2911 2912 /* 2913 * The emlxs_fca_ub_alloc() can be called more than once with different 2914 * size. We will reject the call if there are 2915 * duplicate size with the same FC-4 type. 2916 */ 2917 while (pool) { 2918 if ((pool->pool_type == type) && 2919 (pool->pool_buf_size == size)) { 2920 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 2921 "fca_ub_alloc failed: Unsolicited buffer pool " 2922 "for %s of size 0x%x bytes already exists.", 2923 err, size); 2924 2925 result = FC_FAILURE; 2926 goto fail; 2927 } 2928 2929 pool = pool->pool_next; 2930 } 2931 2932 mutex_exit(&EMLXS_UB_LOCK); 2933 2934 new_pool = (emlxs_unsol_buf_t *)kmem_zalloc(sizeof (emlxs_unsol_buf_t), 2935 KM_SLEEP); 2936 2937 new_pool->pool_next = NULL; 2938 new_pool->pool_type = type; 2939 new_pool->pool_buf_size = size; 2940 new_pool->pool_nentries = *count; 2941 new_pool->pool_available = new_pool->pool_nentries; 2942 new_pool->pool_free = free; 2943 new_pool->pool_free_resv = free_resv; 2944 new_pool->fc_ubufs = 2945 kmem_zalloc((sizeof (fc_unsol_buf_t) * (*count)), KM_SLEEP); 2946 2947 new_pool->pool_first_token = port->ub_count; 2948 new_pool->pool_last_token = port->ub_count + new_pool->pool_nentries; 2949 2950 for (i = 0; i < new_pool->pool_nentries; i++) { 2951 ubp = (fc_unsol_buf_t *)&new_pool->fc_ubufs[i]; 2952 ubp->ub_port_handle = port->ulp_handle; 2953 ubp->ub_token = (uint64_t)((unsigned long)ubp); 2954 ubp->ub_bufsize = size; 2955 ubp->ub_class = FC_TRAN_CLASS3; 2956 ubp->ub_port_private = NULL; 2957 ubp->ub_fca_private = 2958 (emlxs_ub_priv_t *)kmem_zalloc(sizeof (emlxs_ub_priv_t), 2959 KM_SLEEP); 2960 2961 /* 2962 * Initialize emlxs_ub_priv_t 2963 */ 2964 ub_priv = ubp->ub_fca_private; 2965 ub_priv->ubp = ubp; 2966 ub_priv->port = port; 2967 ub_priv->flags = EMLXS_UB_FREE; 2968 ub_priv->available = 1; 2969 ub_priv->pool = new_pool; 2970 ub_priv->time = 0; 2971 ub_priv->timeout = 0; 2972 ub_priv->token = port->ub_count; 2973 ub_priv->cmd = 0; 2974 2975 /* Allocate the actual buffer */ 2976 ubp->ub_buffer = (caddr_t)kmem_zalloc(size, KM_SLEEP); 2977 2978 2979 tokens[i] = (uint64_t)((unsigned long)ubp); 2980 port->ub_count++; 2981 } 2982 2983 mutex_enter(&EMLXS_UB_LOCK); 2984 2985 /* Add the pool to the top of the pool list */ 2986 new_pool->pool_prev = NULL; 2987 new_pool->pool_next = port->ub_pool; 2988 2989 if (port->ub_pool) { 2990 port->ub_pool->pool_prev = new_pool; 2991 } 2992 port->ub_pool = new_pool; 2993 2994 /* Set the post counts */ 2995 if (type == FC_TYPE_IS8802_SNAP) { 2996 MAILBOXQ *mbox; 2997 2998 port->ub_post[hba->channel_ip] += new_pool->pool_nentries; 2999 3000 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 3001 MEM_MBOX))) { 3002 emlxs_mb_config_farp(hba, mbox); 3003 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, 3004 mbox, MBX_NOWAIT, 0); 3005 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 3006 emlxs_mem_put(hba, MEM_MBOX, (void *)mbox); 3007 } 3008 } 3009 port->flag |= EMLXS_PORT_IP_UP; 3010 } else if (type == FC_TYPE_EXTENDED_LS) { 3011 port->ub_post[hba->channel_els] += new_pool->pool_nentries; 3012 } else if (type == FC_TYPE_FC_SERVICES) { 3013 port->ub_post[hba->channel_ct] += new_pool->pool_nentries; 3014 } 3015 3016 mutex_exit(&EMLXS_UB_LOCK); 3017 3018 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 3019 "%d unsolicited buffers allocated for %s of size 0x%x bytes.", 3020 *count, err, size); 3021 3022 return (FC_SUCCESS); 3023 3024 fail: 3025 3026 /* Clean the pool */ 3027 for (i = 0; tokens[i] != NULL; i++) { 3028 /* Get the buffer object */ 3029 ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]); 3030 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; 3031 3032 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, 3033 "fca_ub_alloc failed: Freed buffer=%p token=%x size=%x " 3034 "type=%x ", ubp, ub_priv->token, ubp->ub_bufsize, type); 3035 3036 /* Free the actual buffer */ 3037 kmem_free(ubp->ub_buffer, ubp->ub_bufsize); 3038 3039 /* Free the private area of the buffer object */ 3040 kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t)); 3041 3042 tokens[i] = 0; 3043 port->ub_count--; 3044 } 3045 3046 if (new_pool) { 3047 /* Free the array of buffer objects in the pool */ 3048 kmem_free((caddr_t)new_pool->fc_ubufs, 3049 (sizeof (fc_unsol_buf_t) * new_pool->pool_nentries)); 3050 3051 /* Free the pool object */ 3052 kmem_free((caddr_t)new_pool, sizeof (emlxs_unsol_buf_t)); 3053 } 3054 3055 mutex_exit(&EMLXS_UB_LOCK); 3056 3057 return (result); 3058 3059 } /* emlxs_fca_ub_alloc() */ 3060 3061 3062 static void 3063 emlxs_ub_els_reject(emlxs_port_t *port, fc_unsol_buf_t *ubp) 3064 { 3065 emlxs_hba_t *hba = HBA; 3066 emlxs_ub_priv_t *ub_priv; 3067 fc_packet_t *pkt; 3068 ELS_PKT *els; 3069 uint32_t sid; 3070 3071 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; 3072 3073 if (hba->state <= FC_LINK_DOWN) { 3074 emlxs_abort_els_exchange(hba, port, ubp->ub_frame.rx_id); 3075 return; 3076 } 3077 3078 if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + 3079 sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) { 3080 emlxs_abort_els_exchange(hba, port, ubp->ub_frame.rx_id); 3081 return; 3082 } 3083 3084 sid = LE_SWAP24_LO(ubp->ub_frame.s_id); 3085 3086 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3087 "%s dropped: sid=%x. Rejecting.", 3088 emlxs_elscmd_xlate(ub_priv->cmd), sid); 3089 3090 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 3091 pkt->pkt_timeout = (2 * hba->fc_ratov); 3092 3093 if ((uint32_t)ubp->ub_class == FC_TRAN_CLASS2) { 3094 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3; 3095 pkt->pkt_tran_flags |= FC_TRAN_CLASS2; 3096 } 3097 3098 /* Build the fc header */ 3099 pkt->pkt_cmd_fhdr.d_id = ubp->ub_frame.s_id; 3100 pkt->pkt_cmd_fhdr.r_ctl = 3101 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; 3102 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 3103 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 3104 pkt->pkt_cmd_fhdr.f_ctl = 3105 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 3106 pkt->pkt_cmd_fhdr.seq_id = 0; 3107 pkt->pkt_cmd_fhdr.df_ctl = 0; 3108 pkt->pkt_cmd_fhdr.seq_cnt = 0; 3109 pkt->pkt_cmd_fhdr.ox_id = (ub_priv->cmd >> ELS_CMD_SHIFT) & 0xff; 3110 pkt->pkt_cmd_fhdr.rx_id = ubp->ub_frame.rx_id; 3111 pkt->pkt_cmd_fhdr.ro = 0; 3112 3113 /* Build the command */ 3114 els = (ELS_PKT *) pkt->pkt_cmd; 3115 els->elsCode = 0x01; 3116 els->un.lsRjt.un.b.lsRjtRsvd0 = 0; 3117 els->un.lsRjt.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 3118 els->un.lsRjt.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; 3119 els->un.lsRjt.un.b.vendorUnique = 0x02; 3120 3121 /* Send the pkt later in another thread */ 3122 (void) emlxs_pkt_send(pkt, 0); 3123 3124 return; 3125 3126 } /* emlxs_ub_els_reject() */ 3127 3128 extern int 3129 emlxs_fca_ub_release(opaque_t fca_port_handle, uint32_t count, 3130 uint64_t tokens[]) 3131 { 3132 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 3133 emlxs_hba_t *hba = HBA; 3134 fc_unsol_buf_t *ubp; 3135 emlxs_ub_priv_t *ub_priv; 3136 uint32_t i; 3137 uint32_t time; 3138 emlxs_unsol_buf_t *pool; 3139 3140 if (count == 0) { 3141 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3142 "fca_ub_release: Nothing to do. count=%d", count); 3143 3144 return (FC_SUCCESS); 3145 } 3146 3147 if (!(port->flag & EMLXS_INI_BOUND)) { 3148 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3149 "fca_ub_release failed: Port not bound. count=%d " 3150 "token[0]=%p", 3151 count, tokens[0]); 3152 3153 return (FC_UNBOUND); 3154 } 3155 3156 mutex_enter(&EMLXS_UB_LOCK); 3157 3158 if (!port->ub_pool) { 3159 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3160 "fca_ub_release failed: No pools! count=%d token[0]=%p", 3161 count, tokens[0]); 3162 3163 mutex_exit(&EMLXS_UB_LOCK); 3164 return (FC_UB_BADTOKEN); 3165 } 3166 3167 for (i = 0; i < count; i++) { 3168 ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]); 3169 3170 if (!ubp) { 3171 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3172 "fca_ub_release failed: count=%d tokens[%d]=0", 3173 count, i); 3174 3175 mutex_exit(&EMLXS_UB_LOCK); 3176 return (FC_UB_BADTOKEN); 3177 } 3178 3179 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; 3180 3181 if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) { 3182 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3183 "fca_ub_release failed: Dead buffer found. ubp=%p", 3184 ubp); 3185 3186 mutex_exit(&EMLXS_UB_LOCK); 3187 return (FC_UB_BADTOKEN); 3188 } 3189 3190 if (ub_priv->flags == EMLXS_UB_FREE) { 3191 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3192 "fca_ub_release: Buffer already free! ubp=%p " 3193 "token=%x", 3194 ubp, ub_priv->token); 3195 3196 continue; 3197 } 3198 3199 /* Check for dropped els buffer */ 3200 /* ULP will do this sometimes without sending a reply */ 3201 if ((ubp->ub_frame.r_ctl == FC_ELS_REQ) && 3202 !(ub_priv->flags & EMLXS_UB_REPLY)) { 3203 emlxs_ub_els_reject(port, ubp); 3204 } 3205 3206 /* Mark the buffer free */ 3207 ub_priv->flags = EMLXS_UB_FREE; 3208 bzero(ubp->ub_buffer, ubp->ub_bufsize); 3209 3210 time = hba->timer_tics - ub_priv->time; 3211 ub_priv->time = 0; 3212 ub_priv->timeout = 0; 3213 3214 pool = ub_priv->pool; 3215 3216 if (ub_priv->flags & EMLXS_UB_RESV) { 3217 pool->pool_free_resv++; 3218 } else { 3219 pool->pool_free++; 3220 } 3221 3222 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, 3223 "fca_ub_release: ubp=%p token=%x time=%d av=%d " 3224 "(%d,%d,%d,%d)", 3225 ubp, ub_priv->token, time, ub_priv->available, 3226 pool->pool_nentries, pool->pool_available, 3227 pool->pool_free, pool->pool_free_resv); 3228 3229 /* Check if pool can be destroyed now */ 3230 if ((pool->pool_available == 0) && 3231 (pool->pool_free + pool->pool_free_resv == 3232 pool->pool_nentries)) { 3233 emlxs_ub_destroy(port, pool); 3234 } 3235 } 3236 3237 mutex_exit(&EMLXS_UB_LOCK); 3238 3239 return (FC_SUCCESS); 3240 3241 } /* emlxs_fca_ub_release() */ 3242 3243 3244 static int 3245 emlxs_fca_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) 3246 { 3247 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 3248 emlxs_unsol_buf_t *pool; 3249 fc_unsol_buf_t *ubp; 3250 emlxs_ub_priv_t *ub_priv; 3251 uint32_t i; 3252 3253 if (!(port->flag & EMLXS_INI_ENABLED)) { 3254 return (FC_SUCCESS); 3255 } 3256 3257 if (count == 0) { 3258 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3259 "fca_ub_free: Nothing to do. count=%d token[0]=%p", count, 3260 tokens[0]); 3261 3262 return (FC_SUCCESS); 3263 } 3264 3265 if (!(port->flag & EMLXS_INI_BOUND)) { 3266 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3267 "fca_ub_free: Port not bound. count=%d token[0]=%p", count, 3268 tokens[0]); 3269 3270 return (FC_SUCCESS); 3271 } 3272 3273 mutex_enter(&EMLXS_UB_LOCK); 3274 3275 if (!port->ub_pool) { 3276 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3277 "fca_ub_free failed: No pools! count=%d token[0]=%p", count, 3278 tokens[0]); 3279 3280 mutex_exit(&EMLXS_UB_LOCK); 3281 return (FC_UB_BADTOKEN); 3282 } 3283 3284 /* Process buffer list */ 3285 for (i = 0; i < count; i++) { 3286 ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]); 3287 3288 if (!ubp) { 3289 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3290 "fca_ub_free failed: count=%d tokens[%d]=0", count, 3291 i); 3292 3293 mutex_exit(&EMLXS_UB_LOCK); 3294 return (FC_UB_BADTOKEN); 3295 } 3296 3297 /* Mark buffer unavailable */ 3298 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; 3299 3300 if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) { 3301 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3302 "fca_ub_free failed: Dead buffer found. ubp=%p", 3303 ubp); 3304 3305 mutex_exit(&EMLXS_UB_LOCK); 3306 return (FC_UB_BADTOKEN); 3307 } 3308 3309 ub_priv->available = 0; 3310 3311 /* Mark one less buffer available in the parent pool */ 3312 pool = ub_priv->pool; 3313 3314 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, 3315 "fca_ub_free: ubp=%p token=%x (%d,%d,%d,%d)", ubp, 3316 ub_priv->token, pool->pool_nentries, 3317 pool->pool_available - 1, pool->pool_free, 3318 pool->pool_free_resv); 3319 3320 if (pool->pool_available) { 3321 pool->pool_available--; 3322 3323 /* Check if pool can be destroyed */ 3324 if ((pool->pool_available == 0) && 3325 (pool->pool_free + pool->pool_free_resv == 3326 pool->pool_nentries)) { 3327 emlxs_ub_destroy(port, pool); 3328 } 3329 } 3330 } 3331 3332 mutex_exit(&EMLXS_UB_LOCK); 3333 3334 return (FC_SUCCESS); 3335 3336 } /* emlxs_fca_ub_free() */ 3337 3338 3339 /* EMLXS_UB_LOCK must be held when calling this routine */ 3340 extern void 3341 emlxs_ub_destroy(emlxs_port_t *port, emlxs_unsol_buf_t *pool) 3342 { 3343 emlxs_hba_t *hba = HBA; 3344 emlxs_unsol_buf_t *next; 3345 emlxs_unsol_buf_t *prev; 3346 fc_unsol_buf_t *ubp; 3347 uint32_t i; 3348 3349 /* Remove the pool object from the pool list */ 3350 next = pool->pool_next; 3351 prev = pool->pool_prev; 3352 3353 if (port->ub_pool == pool) { 3354 port->ub_pool = next; 3355 } 3356 3357 if (prev) { 3358 prev->pool_next = next; 3359 } 3360 3361 if (next) { 3362 next->pool_prev = prev; 3363 } 3364 3365 pool->pool_prev = NULL; 3366 pool->pool_next = NULL; 3367 3368 /* Clear the post counts */ 3369 switch (pool->pool_type) { 3370 case FC_TYPE_IS8802_SNAP: 3371 port->ub_post[hba->channel_ip] -= pool->pool_nentries; 3372 break; 3373 3374 case FC_TYPE_EXTENDED_LS: 3375 port->ub_post[hba->channel_els] -= pool->pool_nentries; 3376 break; 3377 3378 case FC_TYPE_FC_SERVICES: 3379 port->ub_post[hba->channel_ct] -= pool->pool_nentries; 3380 break; 3381 } 3382 3383 /* Now free the pool memory */ 3384 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3385 "ub_destroy: pool=%p type=%d size=%d count=%d", pool, 3386 pool->pool_type, pool->pool_buf_size, pool->pool_nentries); 3387 3388 /* Process the array of buffer objects in the pool */ 3389 for (i = 0; i < pool->pool_nentries; i++) { 3390 /* Get the buffer object */ 3391 ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[i]; 3392 3393 /* Free the memory the buffer object represents */ 3394 kmem_free(ubp->ub_buffer, ubp->ub_bufsize); 3395 3396 /* Free the private area of the buffer object */ 3397 kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t)); 3398 } 3399 3400 /* Free the array of buffer objects in the pool */ 3401 kmem_free((caddr_t)pool->fc_ubufs, 3402 (sizeof (fc_unsol_buf_t)*pool->pool_nentries)); 3403 3404 /* Free the pool object */ 3405 kmem_free((caddr_t)pool, sizeof (emlxs_unsol_buf_t)); 3406 3407 return; 3408 3409 } /* emlxs_ub_destroy() */ 3410 3411 3412 /*ARGSUSED*/ 3413 extern int 3414 emlxs_fca_pkt_abort(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) 3415 { 3416 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 3417 emlxs_hba_t *hba = HBA; 3418 emlxs_config_t *cfg = &CFG; 3419 3420 emlxs_buf_t *sbp; 3421 NODELIST *nlp; 3422 NODELIST *prev_nlp; 3423 uint8_t channelno; 3424 CHANNEL *cp; 3425 clock_t pkt_timeout; 3426 clock_t timer; 3427 clock_t time; 3428 int32_t pkt_ret; 3429 IOCBQ *iocbq; 3430 IOCBQ *next; 3431 IOCBQ *prev; 3432 uint32_t found; 3433 uint32_t pass = 0; 3434 3435 sbp = (emlxs_buf_t *)pkt->pkt_fca_private; 3436 iocbq = &sbp->iocbq; 3437 nlp = (NODELIST *)sbp->node; 3438 cp = (CHANNEL *)sbp->channel; 3439 channelno = (cp) ? cp->channelno : 0; 3440 3441 if (!(port->flag & EMLXS_INI_BOUND)) { 3442 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3443 "Port not bound."); 3444 return (FC_UNBOUND); 3445 } 3446 3447 if (!(hba->flag & FC_ONLINE_MODE)) { 3448 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3449 "Adapter offline."); 3450 return (FC_OFFLINE); 3451 } 3452 3453 /* ULP requires the aborted pkt to be completed */ 3454 /* back to ULP before returning from this call. */ 3455 /* SUN knows of problems with this call so they suggested that we */ 3456 /* always return a FC_FAILURE for this call, until it is worked out. */ 3457 3458 /* Check if pkt is no good */ 3459 if (!(sbp->pkt_flags & PACKET_VALID) || 3460 (sbp->pkt_flags & PACKET_ULP_OWNED)) { 3461 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3462 "Bad sbp. flags=%x", sbp->pkt_flags); 3463 return (FC_FAILURE); 3464 } 3465 3466 /* Tag this now */ 3467 /* This will prevent any thread except ours from completing it */ 3468 mutex_enter(&sbp->mtx); 3469 3470 /* Check again if we still own this */ 3471 if (!(sbp->pkt_flags & PACKET_VALID) || 3472 (sbp->pkt_flags & PACKET_ULP_OWNED)) { 3473 mutex_exit(&sbp->mtx); 3474 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3475 "Bad sbp. flags=%x", sbp->pkt_flags); 3476 return (FC_FAILURE); 3477 } 3478 3479 /* Check if pkt is a real polled command */ 3480 if (!(sbp->pkt_flags & PACKET_IN_ABORT) && 3481 (sbp->pkt_flags & PACKET_POLLED)) { 3482 mutex_exit(&sbp->mtx); 3483 3484 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3485 "Attempting to abort a polled I/O. sbp=%p flags=%x", sbp, 3486 sbp->pkt_flags); 3487 return (FC_FAILURE); 3488 } 3489 3490 sbp->pkt_flags |= PACKET_POLLED; 3491 sbp->pkt_flags |= PACKET_IN_ABORT; 3492 3493 if (sbp->pkt_flags & (PACKET_IN_COMPLETION | PACKET_IN_FLUSH | 3494 PACKET_IN_TIMEOUT)) { 3495 mutex_exit(&sbp->mtx); 3496 3497 /* Do nothing, pkt already on its way out */ 3498 goto done; 3499 } 3500 3501 mutex_exit(&sbp->mtx); 3502 3503 begin: 3504 pass++; 3505 3506 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 3507 3508 if (sbp->pkt_flags & PACKET_IN_TXQ) { 3509 /* Find it on the queue */ 3510 found = 0; 3511 if (iocbq->flag & IOCB_PRIORITY) { 3512 /* Search the priority queue */ 3513 prev = NULL; 3514 next = (IOCBQ *) nlp->nlp_ptx[channelno].q_first; 3515 3516 while (next) { 3517 if (next == iocbq) { 3518 /* Remove it */ 3519 if (prev) { 3520 prev->next = iocbq->next; 3521 } 3522 3523 if (nlp->nlp_ptx[channelno].q_last == 3524 (void *)iocbq) { 3525 nlp->nlp_ptx[channelno].q_last = 3526 (void *)prev; 3527 } 3528 3529 if (nlp->nlp_ptx[channelno].q_first == 3530 (void *)iocbq) { 3531 nlp->nlp_ptx[channelno]. 3532 q_first = 3533 (void *)iocbq->next; 3534 } 3535 3536 nlp->nlp_ptx[channelno].q_cnt--; 3537 iocbq->next = NULL; 3538 found = 1; 3539 break; 3540 } 3541 3542 prev = next; 3543 next = next->next; 3544 } 3545 } else { 3546 /* Search the normal queue */ 3547 prev = NULL; 3548 next = (IOCBQ *) nlp->nlp_tx[channelno].q_first; 3549 3550 while (next) { 3551 if (next == iocbq) { 3552 /* Remove it */ 3553 if (prev) { 3554 prev->next = iocbq->next; 3555 } 3556 3557 if (nlp->nlp_tx[channelno].q_last == 3558 (void *)iocbq) { 3559 nlp->nlp_tx[channelno].q_last = 3560 (void *)prev; 3561 } 3562 3563 if (nlp->nlp_tx[channelno].q_first == 3564 (void *)iocbq) { 3565 nlp->nlp_tx[channelno].q_first = 3566 (void *)iocbq->next; 3567 } 3568 3569 nlp->nlp_tx[channelno].q_cnt--; 3570 iocbq->next = NULL; 3571 found = 1; 3572 break; 3573 } 3574 3575 prev = next; 3576 next = (IOCBQ *) next->next; 3577 } 3578 } 3579 3580 if (!found) { 3581 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3582 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3583 "I/O not found in driver. sbp=%p flags=%x", sbp, 3584 sbp->pkt_flags); 3585 goto done; 3586 } 3587 3588 /* Check if node still needs servicing */ 3589 if ((nlp->nlp_ptx[channelno].q_first) || 3590 (nlp->nlp_tx[channelno].q_first && 3591 !(nlp->nlp_flag[channelno] & NLP_CLOSED))) { 3592 3593 /* 3594 * If this is the base node, 3595 * then don't shift the pointers 3596 */ 3597 /* We want to drain the base node before moving on */ 3598 if (!nlp->nlp_base) { 3599 /* Just shift channel queue */ 3600 /* pointers to next node */ 3601 cp->nodeq.q_last = (void *) nlp; 3602 cp->nodeq.q_first = nlp->nlp_next[channelno]; 3603 } 3604 } else { 3605 /* Remove node from channel queue */ 3606 3607 /* If this is the only node on list */ 3608 if (cp->nodeq.q_first == (void *)nlp && 3609 cp->nodeq.q_last == (void *)nlp) { 3610 cp->nodeq.q_last = NULL; 3611 cp->nodeq.q_first = NULL; 3612 cp->nodeq.q_cnt = 0; 3613 } else if (cp->nodeq.q_first == (void *)nlp) { 3614 cp->nodeq.q_first = nlp->nlp_next[channelno]; 3615 ((NODELIST *) cp->nodeq.q_last)-> 3616 nlp_next[channelno] = cp->nodeq.q_first; 3617 cp->nodeq.q_cnt--; 3618 } else { 3619 /* 3620 * This is a little more difficult find the 3621 * previous node in the circular channel queue 3622 */ 3623 prev_nlp = nlp; 3624 while (prev_nlp->nlp_next[channelno] != nlp) { 3625 prev_nlp = prev_nlp-> 3626 nlp_next[channelno]; 3627 } 3628 3629 prev_nlp->nlp_next[channelno] = 3630 nlp->nlp_next[channelno]; 3631 3632 if (cp->nodeq.q_last == (void *)nlp) { 3633 cp->nodeq.q_last = (void *)prev_nlp; 3634 } 3635 cp->nodeq.q_cnt--; 3636 3637 } 3638 3639 /* Clear node */ 3640 nlp->nlp_next[channelno] = NULL; 3641 } 3642 3643 /* Free the ULPIOTAG and the bmp */ 3644 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3645 emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 3646 } else { 3647 (void) emlxs_unregister_pkt(cp, sbp->iotag, 1); 3648 } 3649 3650 3651 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3652 3653 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 3654 IOERR_ABORT_REQUESTED, 1); 3655 3656 goto done; 3657 } 3658 3659 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3660 3661 3662 /* Check the chip queue */ 3663 mutex_enter(&EMLXS_FCTAB_LOCK); 3664 3665 if ((sbp->pkt_flags & PACKET_IN_CHIPQ) && 3666 !(sbp->pkt_flags & PACKET_XRI_CLOSED) && 3667 (sbp == hba->fc_table[sbp->iotag])) { 3668 3669 /* Create the abort IOCB */ 3670 if (hba->state >= FC_LINK_UP) { 3671 iocbq = 3672 emlxs_create_abort_xri_cn(port, sbp->node, 3673 sbp->iotag, cp, sbp->class, ABORT_TYPE_ABTS); 3674 3675 mutex_enter(&sbp->mtx); 3676 sbp->pkt_flags |= PACKET_XRI_CLOSED; 3677 sbp->ticks = 3678 hba->timer_tics + (4 * hba->fc_ratov) + 10; 3679 sbp->abort_attempts++; 3680 mutex_exit(&sbp->mtx); 3681 } else { 3682 iocbq = 3683 emlxs_create_close_xri_cn(port, sbp->node, 3684 sbp->iotag, cp); 3685 3686 mutex_enter(&sbp->mtx); 3687 sbp->pkt_flags |= PACKET_XRI_CLOSED; 3688 sbp->ticks = hba->timer_tics + 30; 3689 sbp->abort_attempts++; 3690 mutex_exit(&sbp->mtx); 3691 } 3692 3693 mutex_exit(&EMLXS_FCTAB_LOCK); 3694 3695 /* Send this iocbq */ 3696 if (iocbq) { 3697 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 3698 iocbq = NULL; 3699 } 3700 3701 goto done; 3702 } 3703 3704 mutex_exit(&EMLXS_FCTAB_LOCK); 3705 3706 /* Pkt was not on any queues */ 3707 3708 /* Check again if we still own this */ 3709 if (!(sbp->pkt_flags & PACKET_VALID) || 3710 (sbp->pkt_flags & 3711 (PACKET_ULP_OWNED | PACKET_IN_COMPLETION | 3712 PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) { 3713 goto done; 3714 } 3715 3716 if (!sleep) { 3717 return (FC_FAILURE); 3718 } 3719 3720 /* Apparently the pkt was not found. Let's delay and try again */ 3721 if (pass < 5) { 3722 delay(drv_usectohz(5000000)); /* 5 seconds */ 3723 3724 /* Check again if we still own this */ 3725 if (!(sbp->pkt_flags & PACKET_VALID) || 3726 (sbp->pkt_flags & 3727 (PACKET_ULP_OWNED | PACKET_IN_COMPLETION | 3728 PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) { 3729 goto done; 3730 } 3731 3732 goto begin; 3733 } 3734 3735 force_it: 3736 3737 /* Force the completion now */ 3738 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3739 "Abort: Completing an IO thats not outstanding: %x", sbp->iotag); 3740 3741 /* Now complete it */ 3742 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_ABORT_REQUESTED, 3743 1); 3744 3745 done: 3746 3747 /* Now wait for the pkt to complete */ 3748 if (!(sbp->pkt_flags & PACKET_COMPLETED)) { 3749 /* Set thread timeout */ 3750 pkt_timeout = emlxs_timeout(hba, 30); 3751 3752 /* Check for panic situation */ 3753 if (ddi_in_panic()) { 3754 3755 /* 3756 * In panic situations there will be one thread with no 3757 * interrrupts (hard or soft) and no timers 3758 */ 3759 3760 /* 3761 * We must manually poll everything in this thread 3762 * to keep the driver going. 3763 */ 3764 3765 /* Keep polling the chip until our IO is completed */ 3766 (void) drv_getparm(LBOLT, &time); 3767 timer = time + drv_usectohz(1000000); 3768 while ((time < pkt_timeout) && 3769 !(sbp->pkt_flags & PACKET_COMPLETED)) { 3770 EMLXS_SLI_POLL_INTR(hba); 3771 (void) drv_getparm(LBOLT, &time); 3772 3773 /* Trigger timer checks periodically */ 3774 if (time >= timer) { 3775 emlxs_timer_checks(hba); 3776 timer = time + drv_usectohz(1000000); 3777 } 3778 } 3779 } else { 3780 /* Wait for IO completion or pkt_timeout */ 3781 mutex_enter(&EMLXS_PKT_LOCK); 3782 pkt_ret = 0; 3783 while ((pkt_ret != -1) && 3784 !(sbp->pkt_flags & PACKET_COMPLETED)) { 3785 pkt_ret = 3786 cv_timedwait(&EMLXS_PKT_CV, 3787 &EMLXS_PKT_LOCK, pkt_timeout); 3788 } 3789 mutex_exit(&EMLXS_PKT_LOCK); 3790 } 3791 3792 /* Check if pkt_timeout occured. This is not good. */ 3793 /* Something happened to our IO. */ 3794 if (!(sbp->pkt_flags & PACKET_COMPLETED)) { 3795 /* Force the completion now */ 3796 goto force_it; 3797 } 3798 } 3799 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 3800 emlxs_unswap_pkt(sbp); 3801 #endif /* EMLXS_MODREV2X */ 3802 3803 /* Check again if we still own this */ 3804 if ((sbp->pkt_flags & PACKET_VALID) && 3805 !(sbp->pkt_flags & PACKET_ULP_OWNED)) { 3806 mutex_enter(&sbp->mtx); 3807 if ((sbp->pkt_flags & PACKET_VALID) && 3808 !(sbp->pkt_flags & PACKET_ULP_OWNED)) { 3809 sbp->pkt_flags |= PACKET_ULP_OWNED; 3810 } 3811 mutex_exit(&sbp->mtx); 3812 } 3813 3814 #ifdef ULP_PATCH5 3815 if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH5) { 3816 return (FC_FAILURE); 3817 } 3818 #endif /* ULP_PATCH5 */ 3819 3820 return (FC_SUCCESS); 3821 3822 } /* emlxs_fca_pkt_abort() */ 3823 3824 3825 static void 3826 emlxs_abort_all(emlxs_hba_t *hba, uint32_t *tx, uint32_t *chip) 3827 { 3828 emlxs_port_t *port = &PPORT; 3829 fc_packet_t *pkt; 3830 emlxs_buf_t *sbp; 3831 uint32_t i; 3832 uint32_t flg; 3833 uint32_t rc; 3834 uint32_t txcnt; 3835 uint32_t chipcnt; 3836 3837 txcnt = 0; 3838 chipcnt = 0; 3839 3840 mutex_enter(&EMLXS_FCTAB_LOCK); 3841 for (i = 0; i < hba->max_iotag; i++) { 3842 sbp = hba->fc_table[i]; 3843 if (sbp == NULL || sbp == STALE_PACKET) { 3844 continue; 3845 } 3846 flg = (sbp->pkt_flags & PACKET_IN_CHIPQ); 3847 pkt = PRIV2PKT(sbp); 3848 mutex_exit(&EMLXS_FCTAB_LOCK); 3849 rc = emlxs_fca_pkt_abort(port, pkt, 0); 3850 if (rc == FC_SUCCESS) { 3851 if (flg) { 3852 chipcnt++; 3853 } else { 3854 txcnt++; 3855 } 3856 } 3857 mutex_enter(&EMLXS_FCTAB_LOCK); 3858 } 3859 mutex_exit(&EMLXS_FCTAB_LOCK); 3860 *tx = txcnt; 3861 *chip = chipcnt; 3862 } /* emlxs_abort_all() */ 3863 3864 3865 extern int32_t 3866 emlxs_reset(emlxs_port_t *port, uint32_t cmd) 3867 { 3868 emlxs_hba_t *hba = HBA; 3869 int rval; 3870 int i = 0; 3871 int ret; 3872 clock_t timeout; 3873 3874 switch (cmd) { 3875 case FC_FCA_LINK_RESET: 3876 3877 mutex_enter(&EMLXS_PORT_LOCK); 3878 if (!(hba->flag & FC_ONLINE_MODE) || 3879 (hba->state <= FC_LINK_DOWN)) { 3880 mutex_exit(&EMLXS_PORT_LOCK); 3881 return (FC_SUCCESS); 3882 } 3883 3884 if (hba->reset_state & 3885 (FC_LINK_RESET_INP | FC_PORT_RESET_INP)) { 3886 mutex_exit(&EMLXS_PORT_LOCK); 3887 return (FC_FAILURE); 3888 } 3889 3890 hba->reset_state |= FC_LINK_RESET_INP; 3891 hba->reset_request |= FC_LINK_RESET; 3892 mutex_exit(&EMLXS_PORT_LOCK); 3893 3894 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3895 "Resetting Link."); 3896 3897 mutex_enter(&EMLXS_LINKUP_LOCK); 3898 hba->linkup_wait_flag = TRUE; 3899 mutex_exit(&EMLXS_LINKUP_LOCK); 3900 3901 if (emlxs_reset_link(hba, 1, 1)) { 3902 mutex_enter(&EMLXS_LINKUP_LOCK); 3903 hba->linkup_wait_flag = FALSE; 3904 mutex_exit(&EMLXS_LINKUP_LOCK); 3905 3906 mutex_enter(&EMLXS_PORT_LOCK); 3907 hba->reset_state &= ~FC_LINK_RESET_INP; 3908 hba->reset_request &= ~FC_LINK_RESET; 3909 mutex_exit(&EMLXS_PORT_LOCK); 3910 3911 return (FC_FAILURE); 3912 } 3913 3914 mutex_enter(&EMLXS_LINKUP_LOCK); 3915 timeout = emlxs_timeout(hba, 60); 3916 ret = 0; 3917 while ((ret != -1) && (hba->linkup_wait_flag == TRUE)) { 3918 ret = 3919 cv_timedwait(&EMLXS_LINKUP_CV, &EMLXS_LINKUP_LOCK, 3920 timeout); 3921 } 3922 3923 hba->linkup_wait_flag = FALSE; 3924 mutex_exit(&EMLXS_LINKUP_LOCK); 3925 3926 mutex_enter(&EMLXS_PORT_LOCK); 3927 hba->reset_state &= ~FC_LINK_RESET_INP; 3928 hba->reset_request &= ~FC_LINK_RESET; 3929 mutex_exit(&EMLXS_PORT_LOCK); 3930 3931 if (ret == -1) { 3932 return (FC_FAILURE); 3933 } 3934 3935 return (FC_SUCCESS); 3936 3937 case FC_FCA_CORE: 3938 #ifdef DUMP_SUPPORT 3939 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3940 "Dumping Core."); 3941 3942 /* Schedule a USER dump */ 3943 emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0); 3944 3945 /* Wait for dump to complete */ 3946 emlxs_dump_wait(hba); 3947 3948 return (FC_SUCCESS); 3949 #endif /* DUMP_SUPPORT */ 3950 3951 case FC_FCA_RESET: 3952 case FC_FCA_RESET_CORE: 3953 3954 mutex_enter(&EMLXS_PORT_LOCK); 3955 if (hba->reset_state & FC_PORT_RESET_INP) { 3956 mutex_exit(&EMLXS_PORT_LOCK); 3957 return (FC_FAILURE); 3958 } 3959 3960 hba->reset_state |= FC_PORT_RESET_INP; 3961 hba->reset_request |= (FC_PORT_RESET | FC_LINK_RESET); 3962 3963 /* wait for any pending link resets to complete */ 3964 while ((hba->reset_state & FC_LINK_RESET_INP) && 3965 (i++ < 1000)) { 3966 mutex_exit(&EMLXS_PORT_LOCK); 3967 delay(drv_usectohz(1000)); 3968 mutex_enter(&EMLXS_PORT_LOCK); 3969 } 3970 3971 if (hba->reset_state & FC_LINK_RESET_INP) { 3972 hba->reset_state &= ~FC_PORT_RESET_INP; 3973 hba->reset_request &= ~(FC_PORT_RESET | FC_LINK_RESET); 3974 mutex_exit(&EMLXS_PORT_LOCK); 3975 return (FC_FAILURE); 3976 } 3977 mutex_exit(&EMLXS_PORT_LOCK); 3978 3979 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3980 "Resetting Adapter."); 3981 3982 rval = FC_SUCCESS; 3983 3984 if (emlxs_offline(hba, 0) == 0) { 3985 (void) emlxs_online(hba); 3986 } else { 3987 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3988 "Adapter reset failed. Device busy."); 3989 3990 rval = FC_DEVICE_BUSY; 3991 } 3992 3993 mutex_enter(&EMLXS_PORT_LOCK); 3994 hba->reset_state &= ~FC_PORT_RESET_INP; 3995 hba->reset_request &= ~(FC_PORT_RESET | FC_LINK_RESET); 3996 mutex_exit(&EMLXS_PORT_LOCK); 3997 3998 return (rval); 3999 4000 case EMLXS_DFC_RESET_ALL: 4001 case EMLXS_DFC_RESET_ALL_FORCE_DUMP: 4002 4003 mutex_enter(&EMLXS_PORT_LOCK); 4004 if (hba->reset_state & FC_PORT_RESET_INP) { 4005 mutex_exit(&EMLXS_PORT_LOCK); 4006 return (FC_FAILURE); 4007 } 4008 4009 hba->reset_state |= FC_PORT_RESET_INP; 4010 hba->reset_request |= (FC_PORT_RESET | FC_LINK_RESET); 4011 4012 /* wait for any pending link resets to complete */ 4013 while ((hba->reset_state & FC_LINK_RESET_INP) && 4014 (i++ < 1000)) { 4015 mutex_exit(&EMLXS_PORT_LOCK); 4016 delay(drv_usectohz(1000)); 4017 mutex_enter(&EMLXS_PORT_LOCK); 4018 } 4019 4020 if (hba->reset_state & FC_LINK_RESET_INP) { 4021 hba->reset_state &= ~FC_PORT_RESET_INP; 4022 hba->reset_request &= ~(FC_PORT_RESET | FC_LINK_RESET); 4023 mutex_exit(&EMLXS_PORT_LOCK); 4024 return (FC_FAILURE); 4025 } 4026 mutex_exit(&EMLXS_PORT_LOCK); 4027 4028 rval = FC_SUCCESS; 4029 4030 if (cmd == EMLXS_DFC_RESET_ALL) { 4031 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4032 "Resetting Adapter (All Firmware Reset)."); 4033 4034 emlxs_sli4_hba_reset_all(hba, 0); 4035 } else { 4036 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4037 "Resetting Adapter " 4038 "(All Firmware Reset, Force Dump)."); 4039 4040 emlxs_sli4_hba_reset_all(hba, 1); 4041 } 4042 4043 mutex_enter(&EMLXS_PORT_LOCK); 4044 hba->reset_state &= ~FC_PORT_RESET_INP; 4045 hba->reset_request &= ~(FC_PORT_RESET | FC_LINK_RESET); 4046 mutex_exit(&EMLXS_PORT_LOCK); 4047 4048 /* Wait for the timer thread to detect the error condition */ 4049 delay(drv_usectohz(1000000)); 4050 4051 /* Wait for the HBA to re-initialize */ 4052 i = 0; 4053 mutex_enter(&EMLXS_PORT_LOCK); 4054 while (!(hba->flag & FC_ONLINE_MODE) && (i++ < 30)) { 4055 mutex_exit(&EMLXS_PORT_LOCK); 4056 delay(drv_usectohz(1000000)); 4057 mutex_enter(&EMLXS_PORT_LOCK); 4058 } 4059 4060 if (!(hba->flag & FC_ONLINE_MODE)) { 4061 rval = FC_FAILURE; 4062 } 4063 4064 mutex_exit(&EMLXS_PORT_LOCK); 4065 4066 return (rval); 4067 4068 default: 4069 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4070 "reset: Unknown command. cmd=%x", cmd); 4071 4072 break; 4073 } 4074 4075 return (FC_FAILURE); 4076 4077 } /* emlxs_reset() */ 4078 4079 4080 extern int32_t 4081 emlxs_fca_reset(opaque_t fca_port_handle, uint32_t cmd) 4082 { 4083 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 4084 emlxs_hba_t *hba = HBA; 4085 int32_t rval; 4086 4087 if (port->mode != MODE_INITIATOR) { 4088 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4089 "fca_reset failed. Port is not in initiator mode."); 4090 4091 return (FC_FAILURE); 4092 } 4093 4094 if (!(port->flag & EMLXS_INI_BOUND)) { 4095 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4096 "fca_reset: Port not bound."); 4097 4098 return (FC_UNBOUND); 4099 } 4100 4101 switch (cmd) { 4102 case FC_FCA_LINK_RESET: 4103 if (hba->fw_flag & FW_UPDATE_NEEDED) { 4104 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4105 "fca_reset: FC_FCA_LINK_RESET -> FC_FCA_RESET"); 4106 cmd = FC_FCA_RESET; 4107 } else { 4108 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4109 "fca_reset: FC_FCA_LINK_RESET"); 4110 } 4111 break; 4112 4113 case FC_FCA_CORE: 4114 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4115 "fca_reset: FC_FCA_CORE"); 4116 break; 4117 4118 case FC_FCA_RESET: 4119 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4120 "fca_reset: FC_FCA_RESET"); 4121 break; 4122 4123 case FC_FCA_RESET_CORE: 4124 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4125 "fca_reset: FC_FCA_RESET_CORE"); 4126 break; 4127 4128 default: 4129 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4130 "fca_reset: Unknown command. cmd=%x", cmd); 4131 return (FC_FAILURE); 4132 } 4133 4134 if (hba->fw_flag & FW_UPDATE_NEEDED) { 4135 hba->fw_flag |= FW_UPDATE_KERNEL; 4136 } 4137 4138 rval = emlxs_reset(port, cmd); 4139 4140 return (rval); 4141 4142 } /* emlxs_fca_reset() */ 4143 4144 4145 extern int 4146 emlxs_fca_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm) 4147 { 4148 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 4149 emlxs_hba_t *hba = HBA; 4150 int32_t ret; 4151 emlxs_vpd_t *vpd = &VPD; 4152 4153 ret = FC_SUCCESS; 4154 4155 #ifdef IDLE_TIMER 4156 emlxs_pm_busy_component(hba); 4157 #endif /* IDLE_TIMER */ 4158 4159 switch (pm->pm_cmd_code) { 4160 4161 case FC_PORT_GET_FW_REV: 4162 { 4163 char buffer[128]; 4164 4165 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4166 "fca_port_manage: FC_PORT_GET_FW_REV"); 4167 4168 (void) snprintf(buffer, (sizeof (buffer)-1), 4169 "%s %s", hba->model_info.model, 4170 vpd->fw_version); 4171 bzero(pm->pm_data_buf, pm->pm_data_len); 4172 4173 if (pm->pm_data_len < strlen(buffer) + 1) { 4174 ret = FC_NOMEM; 4175 4176 break; 4177 } 4178 4179 (void) strncpy(pm->pm_data_buf, buffer, 4180 (pm->pm_data_len-1)); 4181 break; 4182 } 4183 4184 case FC_PORT_GET_FCODE_REV: 4185 { 4186 char buffer[128]; 4187 4188 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4189 "fca_port_manage: FC_PORT_GET_FCODE_REV"); 4190 4191 /* Force update here just to be sure */ 4192 emlxs_get_fcode_version(hba); 4193 4194 (void) snprintf(buffer, (sizeof (buffer)-1), 4195 "%s %s", hba->model_info.model, 4196 vpd->fcode_version); 4197 bzero(pm->pm_data_buf, pm->pm_data_len); 4198 4199 if (pm->pm_data_len < strlen(buffer) + 1) { 4200 ret = FC_NOMEM; 4201 break; 4202 } 4203 4204 (void) strncpy(pm->pm_data_buf, buffer, 4205 (pm->pm_data_len-1)); 4206 break; 4207 } 4208 4209 case FC_PORT_GET_DUMP_SIZE: 4210 { 4211 #ifdef DUMP_SUPPORT 4212 uint32_t dump_size = 0; 4213 4214 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4215 "fca_port_manage: FC_PORT_GET_DUMP_SIZE"); 4216 4217 if (pm->pm_data_len < sizeof (uint32_t)) { 4218 ret = FC_NOMEM; 4219 break; 4220 } 4221 4222 (void) emlxs_get_dump(hba, NULL, &dump_size); 4223 4224 *((uint32_t *)pm->pm_data_buf) = dump_size; 4225 4226 #else 4227 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4228 "fca_port_manage: FC_PORT_GET_DUMP_SIZE unsupported."); 4229 4230 #endif /* DUMP_SUPPORT */ 4231 4232 break; 4233 } 4234 4235 case FC_PORT_GET_DUMP: 4236 { 4237 #ifdef DUMP_SUPPORT 4238 uint32_t dump_size = 0; 4239 4240 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4241 "fca_port_manage: FC_PORT_GET_DUMP"); 4242 4243 (void) emlxs_get_dump(hba, NULL, &dump_size); 4244 4245 if (pm->pm_data_len < dump_size) { 4246 ret = FC_NOMEM; 4247 break; 4248 } 4249 4250 (void) emlxs_get_dump(hba, (uint8_t *)pm->pm_data_buf, 4251 (uint32_t *)&dump_size); 4252 #else 4253 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4254 "fca_port_manage: FC_PORT_GET_DUMP unsupported."); 4255 4256 #endif /* DUMP_SUPPORT */ 4257 4258 break; 4259 } 4260 4261 case FC_PORT_FORCE_DUMP: 4262 { 4263 #ifdef DUMP_SUPPORT 4264 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4265 "fca_port_manage: FC_PORT_FORCE_DUMP"); 4266 4267 /* Schedule a USER dump */ 4268 emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0); 4269 4270 /* Wait for dump to complete */ 4271 emlxs_dump_wait(hba); 4272 #else 4273 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4274 "fca_port_manage: FC_PORT_FORCE_DUMP unsupported."); 4275 4276 #endif /* DUMP_SUPPORT */ 4277 break; 4278 } 4279 4280 case FC_PORT_LINK_STATE: 4281 { 4282 uint32_t *link_state; 4283 4284 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4285 "fca_port_manage: FC_PORT_LINK_STATE"); 4286 4287 if (pm->pm_stat_len != sizeof (*link_state)) { 4288 ret = FC_NOMEM; 4289 break; 4290 } 4291 4292 if (pm->pm_cmd_buf != NULL) { 4293 /* 4294 * Can't look beyond the FCA port. 4295 */ 4296 ret = FC_INVALID_REQUEST; 4297 break; 4298 } 4299 4300 link_state = (uint32_t *)pm->pm_stat_buf; 4301 4302 /* Set the state */ 4303 if (hba->state >= FC_LINK_UP) { 4304 /* Check for loop topology */ 4305 if (hba->topology == TOPOLOGY_LOOP) { 4306 *link_state = FC_STATE_LOOP; 4307 } else { 4308 *link_state = FC_STATE_ONLINE; 4309 } 4310 4311 /* Set the link speed */ 4312 switch (hba->linkspeed) { 4313 case LA_2GHZ_LINK: 4314 *link_state |= FC_STATE_2GBIT_SPEED; 4315 break; 4316 case LA_4GHZ_LINK: 4317 *link_state |= FC_STATE_4GBIT_SPEED; 4318 break; 4319 case LA_8GHZ_LINK: 4320 *link_state |= FC_STATE_8GBIT_SPEED; 4321 break; 4322 case LA_10GHZ_LINK: 4323 *link_state |= FC_STATE_10GBIT_SPEED; 4324 break; 4325 case LA_16GHZ_LINK: 4326 *link_state |= FC_STATE_16GBIT_SPEED; 4327 break; 4328 case LA_1GHZ_LINK: 4329 default: 4330 *link_state |= FC_STATE_1GBIT_SPEED; 4331 break; 4332 } 4333 } else { 4334 *link_state = FC_STATE_OFFLINE; 4335 } 4336 4337 break; 4338 } 4339 4340 4341 case FC_PORT_ERR_STATS: 4342 case FC_PORT_RLS: 4343 { 4344 MAILBOXQ *mbq; 4345 MAILBOX *mb; 4346 fc_rls_acc_t *bp; 4347 4348 if (!(hba->flag & FC_ONLINE_MODE)) { 4349 return (FC_OFFLINE); 4350 } 4351 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4352 "fca_port_manage: FC_PORT_RLS / FC_PORT_ERR_STATS"); 4353 4354 if (pm->pm_data_len < sizeof (fc_rls_acc_t)) { 4355 ret = FC_NOMEM; 4356 break; 4357 } 4358 4359 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, 4360 MEM_MBOX)) == 0) { 4361 ret = FC_NOMEM; 4362 break; 4363 } 4364 mb = (MAILBOX *)mbq; 4365 4366 emlxs_mb_read_lnk_stat(hba, mbq); 4367 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) 4368 != MBX_SUCCESS) { 4369 ret = FC_PBUSY; 4370 } else { 4371 bp = (fc_rls_acc_t *)pm->pm_data_buf; 4372 4373 bp->rls_link_fail = mb->un.varRdLnk.linkFailureCnt; 4374 bp->rls_sync_loss = mb->un.varRdLnk.lossSyncCnt; 4375 bp->rls_sig_loss = mb->un.varRdLnk.lossSignalCnt; 4376 bp->rls_prim_seq_err = mb->un.varRdLnk.primSeqErrCnt; 4377 bp->rls_invalid_word = 4378 mb->un.varRdLnk.invalidXmitWord; 4379 bp->rls_invalid_crc = mb->un.varRdLnk.crcCnt; 4380 } 4381 4382 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 4383 break; 4384 } 4385 4386 case FC_PORT_DOWNLOAD_FW: 4387 if (!(hba->flag & FC_ONLINE_MODE)) { 4388 return (FC_OFFLINE); 4389 } 4390 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4391 "fca_port_manage: FC_PORT_DOWNLOAD_FW"); 4392 ret = emlxs_fw_download(hba, pm->pm_data_buf, 4393 pm->pm_data_len, 1); 4394 break; 4395 4396 case FC_PORT_DOWNLOAD_FCODE: 4397 if (!(hba->flag & FC_ONLINE_MODE)) { 4398 return (FC_OFFLINE); 4399 } 4400 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4401 "fca_port_manage: FC_PORT_DOWNLOAD_FCODE"); 4402 ret = emlxs_fw_download(hba, pm->pm_data_buf, 4403 pm->pm_data_len, 1); 4404 break; 4405 4406 case FC_PORT_DIAG: 4407 { 4408 uint32_t errno = 0; 4409 uint32_t did = 0; 4410 uint32_t pattern = 0; 4411 4412 switch (pm->pm_cmd_flags) { 4413 case EMLXS_DIAG_BIU: 4414 4415 if (!(hba->flag & FC_ONLINE_MODE)) { 4416 return (FC_OFFLINE); 4417 } 4418 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4419 "fca_port_manage: DIAG_BIU"); 4420 4421 if (pm->pm_data_len) { 4422 pattern = *((uint32_t *)pm->pm_data_buf); 4423 } 4424 4425 errno = emlxs_diag_biu_run(hba, pattern); 4426 4427 if (pm->pm_stat_len == sizeof (errno)) { 4428 *(int *)pm->pm_stat_buf = errno; 4429 } 4430 4431 break; 4432 4433 4434 case EMLXS_DIAG_POST: 4435 4436 if (!(hba->flag & FC_ONLINE_MODE)) { 4437 return (FC_OFFLINE); 4438 } 4439 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4440 "fca_port_manage: DIAG_POST"); 4441 4442 errno = emlxs_diag_post_run(hba); 4443 4444 if (pm->pm_stat_len == sizeof (errno)) { 4445 *(int *)pm->pm_stat_buf = errno; 4446 } 4447 4448 break; 4449 4450 4451 case EMLXS_DIAG_ECHO: 4452 4453 if (!(hba->flag & FC_ONLINE_MODE)) { 4454 return (FC_OFFLINE); 4455 } 4456 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4457 "fca_port_manage: DIAG_ECHO"); 4458 4459 if (pm->pm_cmd_len != sizeof (uint32_t)) { 4460 ret = FC_INVALID_REQUEST; 4461 break; 4462 } 4463 4464 did = *((uint32_t *)pm->pm_cmd_buf); 4465 4466 if (pm->pm_data_len) { 4467 pattern = *((uint32_t *)pm->pm_data_buf); 4468 } 4469 4470 errno = emlxs_diag_echo_run(port, did, pattern); 4471 4472 if (pm->pm_stat_len == sizeof (errno)) { 4473 *(int *)pm->pm_stat_buf = errno; 4474 } 4475 4476 break; 4477 4478 4479 case EMLXS_PARM_GET_NUM: 4480 { 4481 uint32_t *num; 4482 emlxs_config_t *cfg; 4483 uint32_t i; 4484 uint32_t count; 4485 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4486 "fca_port_manage: PARM_GET_NUM"); 4487 4488 if (pm->pm_stat_len < sizeof (uint32_t)) { 4489 ret = FC_NOMEM; 4490 break; 4491 } 4492 4493 num = (uint32_t *)pm->pm_stat_buf; 4494 count = 0; 4495 cfg = &CFG; 4496 for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) { 4497 if (!(cfg->flags & PARM_HIDDEN)) { 4498 count++; 4499 } 4500 4501 } 4502 4503 *num = count; 4504 4505 break; 4506 } 4507 4508 case EMLXS_PARM_GET_LIST: 4509 { 4510 emlxs_parm_t *parm; 4511 emlxs_config_t *cfg; 4512 uint32_t i; 4513 uint32_t max_count; 4514 4515 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4516 "fca_port_manage: PARM_GET_LIST"); 4517 4518 if (pm->pm_stat_len < sizeof (emlxs_parm_t)) { 4519 ret = FC_NOMEM; 4520 break; 4521 } 4522 4523 max_count = pm->pm_stat_len / sizeof (emlxs_parm_t); 4524 4525 parm = (emlxs_parm_t *)pm->pm_stat_buf; 4526 cfg = &CFG; 4527 for (i = 0; i < NUM_CFG_PARAM && max_count; i++, 4528 cfg++) { 4529 if (!(cfg->flags & PARM_HIDDEN)) { 4530 (void) strncpy(parm->label, cfg->string, 4531 (sizeof (parm->label)-1)); 4532 parm->min = cfg->low; 4533 parm->max = cfg->hi; 4534 parm->def = cfg->def; 4535 parm->current = cfg->current; 4536 parm->flags = cfg->flags; 4537 (void) strncpy(parm->help, cfg->help, 4538 (sizeof (parm->help)-1)); 4539 parm++; 4540 max_count--; 4541 } 4542 } 4543 4544 break; 4545 } 4546 4547 case EMLXS_PARM_GET: 4548 { 4549 emlxs_parm_t *parm_in; 4550 emlxs_parm_t *parm_out; 4551 emlxs_config_t *cfg; 4552 uint32_t i; 4553 uint32_t len; 4554 4555 if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) { 4556 EMLXS_MSGF(EMLXS_CONTEXT, 4557 &emlxs_sfs_debug_msg, 4558 "fca_port_manage: PARM_GET. " 4559 "inbuf too small."); 4560 4561 ret = FC_BADCMD; 4562 break; 4563 } 4564 4565 if (pm->pm_stat_len < sizeof (emlxs_parm_t)) { 4566 EMLXS_MSGF(EMLXS_CONTEXT, 4567 &emlxs_sfs_debug_msg, 4568 "fca_port_manage: PARM_GET. " 4569 "outbuf too small"); 4570 4571 ret = FC_BADCMD; 4572 break; 4573 } 4574 4575 parm_in = (emlxs_parm_t *)pm->pm_cmd_buf; 4576 parm_out = (emlxs_parm_t *)pm->pm_stat_buf; 4577 len = strlen(parm_in->label); 4578 cfg = &CFG; 4579 ret = FC_BADOBJECT; 4580 4581 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4582 "fca_port_manage: PARM_GET: %s=0x%x,%d", 4583 parm_in->label, parm_in->current, 4584 parm_in->current); 4585 4586 for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) { 4587 if (len == strlen(cfg->string) && 4588 (strcmp(parm_in->label, 4589 cfg->string) == 0)) { 4590 (void) strncpy(parm_out->label, 4591 cfg->string, 4592 (sizeof (parm_out->label)-1)); 4593 parm_out->min = cfg->low; 4594 parm_out->max = cfg->hi; 4595 parm_out->def = cfg->def; 4596 parm_out->current = cfg->current; 4597 parm_out->flags = cfg->flags; 4598 (void) strncpy(parm_out->help, 4599 cfg->help, 4600 (sizeof (parm_out->help)-1)); 4601 4602 ret = FC_SUCCESS; 4603 break; 4604 } 4605 } 4606 4607 break; 4608 } 4609 4610 case EMLXS_PARM_SET: 4611 { 4612 emlxs_parm_t *parm_in; 4613 emlxs_parm_t *parm_out; 4614 emlxs_config_t *cfg; 4615 uint32_t i; 4616 uint32_t len; 4617 4618 if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) { 4619 EMLXS_MSGF(EMLXS_CONTEXT, 4620 &emlxs_sfs_debug_msg, 4621 "fca_port_manage: PARM_GET. " 4622 "inbuf too small."); 4623 4624 ret = FC_BADCMD; 4625 break; 4626 } 4627 4628 if (pm->pm_stat_len < sizeof (emlxs_parm_t)) { 4629 EMLXS_MSGF(EMLXS_CONTEXT, 4630 &emlxs_sfs_debug_msg, 4631 "fca_port_manage: PARM_GET. " 4632 "outbuf too small"); 4633 ret = FC_BADCMD; 4634 break; 4635 } 4636 4637 parm_in = (emlxs_parm_t *)pm->pm_cmd_buf; 4638 parm_out = (emlxs_parm_t *)pm->pm_stat_buf; 4639 len = strlen(parm_in->label); 4640 cfg = &CFG; 4641 ret = FC_BADOBJECT; 4642 4643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4644 "fca_port_manage: PARM_SET: %s=0x%x,%d", 4645 parm_in->label, parm_in->current, 4646 parm_in->current); 4647 4648 for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) { 4649 /* Find matching parameter string */ 4650 if (len == strlen(cfg->string) && 4651 (strcmp(parm_in->label, 4652 cfg->string) == 0)) { 4653 /* Attempt to update parameter */ 4654 if (emlxs_set_parm(hba, i, 4655 parm_in->current) == FC_SUCCESS) { 4656 (void) strncpy(parm_out->label, 4657 cfg->string, 4658 (sizeof (parm_out->label)- 4659 1)); 4660 parm_out->min = cfg->low; 4661 parm_out->max = cfg->hi; 4662 parm_out->def = cfg->def; 4663 parm_out->current = 4664 cfg->current; 4665 parm_out->flags = cfg->flags; 4666 (void) strncpy(parm_out->help, 4667 cfg->help, 4668 (sizeof (parm_out->help)- 4669 1)); 4670 4671 ret = FC_SUCCESS; 4672 } 4673 4674 break; 4675 } 4676 } 4677 4678 break; 4679 } 4680 4681 case EMLXS_LOG_GET: 4682 { 4683 emlxs_log_req_t *req; 4684 emlxs_log_resp_t *resp; 4685 uint32_t len; 4686 4687 /* Check command size */ 4688 if (pm->pm_cmd_len < sizeof (emlxs_log_req_t)) { 4689 ret = FC_BADCMD; 4690 break; 4691 } 4692 4693 /* Get the request */ 4694 req = (emlxs_log_req_t *)pm->pm_cmd_buf; 4695 4696 /* Calculate the response length from the request */ 4697 len = sizeof (emlxs_log_resp_t) + 4698 (req->count * MAX_LOG_MSG_LENGTH); 4699 4700 /* Check the response buffer length */ 4701 if (pm->pm_stat_len < len) { 4702 ret = FC_BADCMD; 4703 break; 4704 } 4705 4706 /* Get the response pointer */ 4707 resp = (emlxs_log_resp_t *)pm->pm_stat_buf; 4708 4709 /* Get the request log enties */ 4710 (void) emlxs_msg_log_get(hba, req, resp); 4711 4712 ret = FC_SUCCESS; 4713 break; 4714 } 4715 4716 case EMLXS_GET_BOOT_REV: 4717 { 4718 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4719 "fca_port_manage: GET_BOOT_REV"); 4720 4721 if (pm->pm_stat_len < strlen(vpd->boot_version)) { 4722 ret = FC_NOMEM; 4723 break; 4724 } 4725 4726 bzero(pm->pm_stat_buf, pm->pm_stat_len); 4727 (void) snprintf(pm->pm_stat_buf, pm->pm_stat_len, 4728 "%s %s", hba->model_info.model, vpd->boot_version); 4729 4730 break; 4731 } 4732 4733 case EMLXS_DOWNLOAD_BOOT: 4734 if (!(hba->flag & FC_ONLINE_MODE)) { 4735 return (FC_OFFLINE); 4736 } 4737 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4738 "fca_port_manage: DOWNLOAD_BOOT"); 4739 4740 ret = emlxs_fw_download(hba, pm->pm_data_buf, 4741 pm->pm_data_len, 1); 4742 break; 4743 4744 case EMLXS_DOWNLOAD_CFL: 4745 { 4746 uint32_t *buffer; 4747 uint32_t region; 4748 uint32_t length; 4749 4750 if (!(hba->flag & FC_ONLINE_MODE)) { 4751 return (FC_OFFLINE); 4752 } 4753 4754 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4755 "fca_port_manage: DOWNLOAD_CFL"); 4756 4757 /* Extract the region number from the first word. */ 4758 buffer = (uint32_t *)pm->pm_data_buf; 4759 region = *buffer++; 4760 4761 /* Adjust the image length for the header word */ 4762 length = pm->pm_data_len - 4; 4763 4764 ret = 4765 emlxs_cfl_download(hba, region, (caddr_t)buffer, 4766 length); 4767 break; 4768 } 4769 4770 case EMLXS_VPD_GET: 4771 { 4772 emlxs_vpd_desc_t *vpd_out; 4773 4774 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4775 "fca_port_manage: VPD_GET"); 4776 4777 if (pm->pm_stat_len < sizeof (emlxs_vpd_desc_t)) { 4778 ret = FC_BADCMD; 4779 break; 4780 } 4781 4782 vpd_out = (emlxs_vpd_desc_t *)pm->pm_stat_buf; 4783 bzero(vpd_out, pm->pm_stat_len); 4784 4785 (void) strncpy(vpd_out->id, vpd->id, 4786 (sizeof (vpd_out->id)-1)); 4787 (void) strncpy(vpd_out->part_num, vpd->part_num, 4788 (sizeof (vpd_out->part_num)-1)); 4789 (void) strncpy(vpd_out->eng_change, vpd->eng_change, 4790 (sizeof (vpd_out->eng_change)-1)); 4791 (void) strncpy(vpd_out->manufacturer, vpd->manufacturer, 4792 (sizeof (vpd_out->manufacturer)-1)); 4793 (void) strncpy(vpd_out->serial_num, vpd->serial_num, 4794 (sizeof (vpd_out->serial_num)-1)); 4795 (void) strncpy(vpd_out->model, vpd->model, 4796 (sizeof (vpd_out->model)-1)); 4797 (void) strncpy(vpd_out->model_desc, vpd->model_desc, 4798 (sizeof (vpd_out->model_desc)-1)); 4799 (void) strncpy(vpd_out->port_num, vpd->port_num, 4800 (sizeof (vpd_out->port_num)-1)); 4801 (void) strncpy(vpd_out->prog_types, vpd->prog_types, 4802 (sizeof (vpd_out->prog_types)-1)); 4803 4804 ret = FC_SUCCESS; 4805 4806 break; 4807 } 4808 4809 case EMLXS_VPD_GET_V2: 4810 { 4811 emlxs_vpd_desc_v2_t *vpd_out; 4812 4813 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4814 "fca_port_manage: VPD_GET_V2"); 4815 4816 if (pm->pm_stat_len < sizeof (emlxs_vpd_desc_v2_t)) { 4817 ret = FC_BADCMD; 4818 break; 4819 } 4820 4821 vpd_out = (emlxs_vpd_desc_v2_t *)pm->pm_stat_buf; 4822 bzero(vpd_out, pm->pm_stat_len); 4823 4824 (void) strncpy(vpd_out->id, vpd->id, 4825 (sizeof (vpd_out->id)-1)); 4826 (void) strncpy(vpd_out->part_num, vpd->part_num, 4827 (sizeof (vpd_out->part_num)-1)); 4828 (void) strncpy(vpd_out->eng_change, vpd->eng_change, 4829 (sizeof (vpd_out->eng_change)-1)); 4830 (void) strncpy(vpd_out->manufacturer, vpd->manufacturer, 4831 (sizeof (vpd_out->manufacturer)-1)); 4832 (void) strncpy(vpd_out->serial_num, vpd->serial_num, 4833 (sizeof (vpd_out->serial_num)-1)); 4834 (void) strncpy(vpd_out->model, vpd->model, 4835 (sizeof (vpd_out->model)-1)); 4836 (void) strncpy(vpd_out->model_desc, vpd->model_desc, 4837 (sizeof (vpd_out->model_desc)-1)); 4838 (void) strncpy(vpd_out->port_num, vpd->port_num, 4839 (sizeof (vpd_out->port_num)-1)); 4840 (void) strncpy(vpd_out->prog_types, vpd->prog_types, 4841 (sizeof (vpd_out->prog_types)-1)); 4842 4843 ret = FC_SUCCESS; 4844 4845 break; 4846 } 4847 4848 case EMLXS_PHY_GET: 4849 { 4850 emlxs_phy_desc_t *phy_out; 4851 MAILBOXQ *mbq; 4852 MAILBOX4 *mb; 4853 IOCTL_COMMON_GET_PHY_DETAILS *phy; 4854 mbox_req_hdr_t *hdr_req; 4855 4856 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4857 "fca_port_manage: EMLXS_PHY_GET"); 4858 4859 if (pm->pm_stat_len < sizeof (emlxs_phy_desc_t)) { 4860 ret = FC_BADCMD; 4861 break; 4862 } 4863 4864 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 4865 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4866 "Invalid sli_mode. mode=%d", hba->sli_mode); 4867 ret = FC_BADCMD; 4868 break; 4869 } 4870 4871 phy_out = (emlxs_phy_desc_t *)pm->pm_stat_buf; 4872 bzero(phy_out, sizeof (emlxs_phy_desc_t)); 4873 4874 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, 4875 MEM_MBOX)) == 0) { 4876 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4877 "Unable to allocate mailbox buffer."); 4878 ret = FC_NOMEM; 4879 break; 4880 } 4881 4882 mb = (MAILBOX4*)mbq; 4883 4884 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 4885 4886 mb->un.varSLIConfig.be.embedded = 1; 4887 mbq->mbox_cmpl = NULL; 4888 4889 mb->mbxCommand = MBX_SLI_CONFIG; 4890 mb->mbxOwner = OWN_HOST; 4891 4892 hdr_req = (mbox_req_hdr_t *) 4893 &mb->un.varSLIConfig.be.un_hdr.hdr_req; 4894 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; 4895 hdr_req->opcode = COMMON_OPCODE_GET_PHY_DETAILS; 4896 hdr_req->timeout = 0; 4897 hdr_req->req_length = 4898 sizeof (IOCTL_COMMON_GET_PHY_DETAILS); 4899 4900 phy = (IOCTL_COMMON_GET_PHY_DETAILS *)(hdr_req + 1); 4901 4902 /* Send read request */ 4903 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 4904 MBX_SUCCESS) { 4905 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4906 "Unable to get PHY details. status=%x", 4907 mb->mbxStatus); 4908 4909 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 4910 4911 ret = FC_FAILURE; 4912 break; 4913 } 4914 4915 phy_out->phy_type = phy->params.response.phy_type; 4916 phy_out->interface_type = 4917 phy->params.response.interface_type; 4918 phy_out->misc_params = phy->params.response.misc_params; 4919 phy_out->rsvd[0] = phy->params.response.rsvd[0]; 4920 phy_out->rsvd[1] = phy->params.response.rsvd[1]; 4921 phy_out->rsvd[2] = phy->params.response.rsvd[2]; 4922 phy_out->rsvd[3] = phy->params.response.rsvd[3]; 4923 4924 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 4925 4926 ret = FC_SUCCESS; 4927 break; 4928 } 4929 4930 #ifdef NODE_THROTTLE_SUPPORT 4931 case EMLXS_SET_THROTTLE: 4932 { 4933 emlxs_node_t *node; 4934 uint32_t scope = 0; 4935 uint32_t i; 4936 char buf1[32]; 4937 emlxs_throttle_desc_t *desc; 4938 4939 if ((pm->pm_data_buf == NULL) || 4940 (pm->pm_data_len != 4941 sizeof (emlxs_throttle_desc_t))) { 4942 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4943 "fca_port_manage: EMLXS_SET_THROTTLE: " 4944 "Descriptor buffer not valid. %d", 4945 pm->pm_data_len); 4946 ret = FC_BADCMD; 4947 break; 4948 } 4949 4950 if ((pm->pm_cmd_buf != NULL) && 4951 (pm->pm_cmd_len == sizeof (uint32_t))) { 4952 scope = *(uint32_t *)pm->pm_cmd_buf; 4953 } 4954 4955 desc = (emlxs_throttle_desc_t *)pm->pm_data_buf; 4956 desc->throttle = MIN(desc->throttle, MAX_NODE_THROTTLE); 4957 4958 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4959 "fca_port_manage: EMLXS_SET_THROTTLE: scope=%d " 4960 "depth=%d", 4961 scope, desc->throttle); 4962 4963 rw_enter(&port->node_rwlock, RW_WRITER); 4964 switch (scope) { 4965 case 1: /* all */ 4966 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 4967 node = port->node_table[i]; 4968 while (node != NULL) { 4969 node->io_throttle = desc->throttle; 4970 4971 EMLXS_MSGF(EMLXS_CONTEXT, 4972 &emlxs_sfs_debug_msg, 4973 "EMLXS_SET_THROTTLE: wwpn=%s " 4974 "depth=%d", 4975 emlxs_wwn_xlate(buf1, sizeof (buf1), 4976 (uint8_t *)&node->nlp_portname), 4977 node->io_throttle); 4978 4979 node = (NODELIST *)node->nlp_list_next; 4980 } 4981 } 4982 break; 4983 4984 case 2: /* FCP */ 4985 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 4986 node = port->node_table[i]; 4987 while (node != NULL) { 4988 if (!(node->nlp_fcp_info & 4989 NLP_FCP_TGT_DEVICE)) { 4990 node = (NODELIST *) 4991 node->nlp_list_next; 4992 continue; 4993 } 4994 4995 node->io_throttle = desc->throttle; 4996 4997 EMLXS_MSGF(EMLXS_CONTEXT, 4998 &emlxs_sfs_debug_msg, 4999 "EMLXS_SET_THROTTLE: wwpn=%s " 5000 "depth=%d", 5001 emlxs_wwn_xlate(buf1, sizeof (buf1), 5002 (uint8_t *)&node->nlp_portname), 5003 node->io_throttle); 5004 5005 node = (NODELIST *)node->nlp_list_next; 5006 } 5007 } 5008 break; 5009 5010 case 0: /* WWPN */ 5011 default: 5012 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 5013 node = port->node_table[i]; 5014 while (node != NULL) { 5015 if (bcmp((caddr_t)&node->nlp_portname, 5016 desc->wwpn, 8)) { 5017 node = (NODELIST *) 5018 node->nlp_list_next; 5019 continue; 5020 } 5021 5022 node->io_throttle = desc->throttle; 5023 5024 EMLXS_MSGF(EMLXS_CONTEXT, 5025 &emlxs_sfs_debug_msg, 5026 "EMLXS_SET_THROTTLE: wwpn=%s " 5027 "depth=%d", 5028 emlxs_wwn_xlate(buf1, sizeof (buf1), 5029 (uint8_t *)&node->nlp_portname), 5030 node->io_throttle); 5031 5032 goto set_throttle_done; 5033 } 5034 } 5035 set_throttle_done: 5036 break; 5037 } 5038 5039 rw_exit(&port->node_rwlock); 5040 ret = FC_SUCCESS; 5041 5042 break; 5043 } 5044 5045 case EMLXS_GET_THROTTLE: 5046 { 5047 emlxs_node_t *node; 5048 uint32_t i; 5049 uint32_t j; 5050 char buf1[32]; 5051 uint32_t count; 5052 emlxs_throttle_desc_t *desc; 5053 5054 if (pm->pm_stat_len == sizeof (uint32_t)) { 5055 count = emlxs_nport_count(port); 5056 *(uint32_t *)pm->pm_stat_buf = count; 5057 5058 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5059 "fca_port_manage: EMLXS_GET_THROTTLE: " 5060 "count=%d", 5061 count); 5062 5063 ret = FC_SUCCESS; 5064 break; 5065 } 5066 5067 if ((pm->pm_stat_buf == NULL) || 5068 (pm->pm_stat_len < 5069 sizeof (emlxs_throttle_desc_t))) { 5070 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5071 "fca_port_manage: EMLXS_GET_THROTTLE: " 5072 "Descriptor buffer too small. %d", 5073 pm->pm_data_len); 5074 ret = FC_BADCMD; 5075 break; 5076 } 5077 5078 count = pm->pm_stat_len / 5079 sizeof (emlxs_throttle_desc_t); 5080 desc = (emlxs_throttle_desc_t *)pm->pm_stat_buf; 5081 5082 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5083 "fca_port_manage: EMLXS_GET_THROTTLE: max=%d", 5084 count); 5085 5086 rw_enter(&port->node_rwlock, RW_READER); 5087 j = 0; 5088 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 5089 node = port->node_table[i]; 5090 while (node != NULL) { 5091 if ((node->nlp_DID & 0xFFF000) == 5092 0xFFF000) { 5093 node = (NODELIST *) 5094 node->nlp_list_next; 5095 continue; 5096 } 5097 5098 bcopy((uint8_t *)&node->nlp_portname, 5099 desc[j].wwpn, 8); 5100 desc[j].throttle = node->io_throttle; 5101 5102 EMLXS_MSGF(EMLXS_CONTEXT, 5103 &emlxs_sfs_debug_msg, 5104 "EMLXS_GET_THROTTLE: wwpn=%s " 5105 "depth=%d", 5106 emlxs_wwn_xlate(buf1, sizeof (buf1), 5107 desc[j].wwpn), 5108 desc[j].throttle); 5109 5110 j++; 5111 if (j >= count) { 5112 goto get_throttle_done; 5113 } 5114 5115 node = (NODELIST *)node->nlp_list_next; 5116 } 5117 } 5118 get_throttle_done: 5119 rw_exit(&port->node_rwlock); 5120 ret = FC_SUCCESS; 5121 5122 break; 5123 } 5124 #endif /* NODE_THROTTLE_SUPPORT */ 5125 5126 case EMLXS_GET_FCIO_REV: 5127 { 5128 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5129 "fca_port_manage: GET_FCIO_REV"); 5130 5131 if (pm->pm_stat_len < sizeof (uint32_t)) { 5132 ret = FC_NOMEM; 5133 break; 5134 } 5135 5136 bzero(pm->pm_stat_buf, pm->pm_stat_len); 5137 *(uint32_t *)pm->pm_stat_buf = FCIO_REV; 5138 5139 break; 5140 } 5141 5142 case EMLXS_GET_DFC_REV: 5143 { 5144 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5145 "fca_port_manage: GET_DFC_REV"); 5146 5147 if (pm->pm_stat_len < sizeof (uint32_t)) { 5148 ret = FC_NOMEM; 5149 break; 5150 } 5151 5152 bzero(pm->pm_stat_buf, pm->pm_stat_len); 5153 *(uint32_t *)pm->pm_stat_buf = DFC_REV; 5154 5155 break; 5156 } 5157 5158 case EMLXS_SET_BOOT_STATE: 5159 case EMLXS_SET_BOOT_STATE_old: 5160 { 5161 uint32_t state; 5162 5163 if (!(hba->flag & FC_ONLINE_MODE)) { 5164 return (FC_OFFLINE); 5165 } 5166 if (pm->pm_cmd_len < sizeof (uint32_t)) { 5167 EMLXS_MSGF(EMLXS_CONTEXT, 5168 &emlxs_sfs_debug_msg, 5169 "fca_port_manage: SET_BOOT_STATE"); 5170 ret = FC_BADCMD; 5171 break; 5172 } 5173 5174 state = *(uint32_t *)pm->pm_cmd_buf; 5175 5176 if (state == 0) { 5177 EMLXS_MSGF(EMLXS_CONTEXT, 5178 &emlxs_sfs_debug_msg, 5179 "fca_port_manage: SET_BOOT_STATE: " 5180 "Disable"); 5181 ret = emlxs_boot_code_disable(hba); 5182 } else { 5183 EMLXS_MSGF(EMLXS_CONTEXT, 5184 &emlxs_sfs_debug_msg, 5185 "fca_port_manage: SET_BOOT_STATE: " 5186 "Enable"); 5187 ret = emlxs_boot_code_enable(hba); 5188 } 5189 5190 break; 5191 } 5192 5193 case EMLXS_GET_BOOT_STATE: 5194 case EMLXS_GET_BOOT_STATE_old: 5195 { 5196 if (!(hba->flag & FC_ONLINE_MODE)) { 5197 return (FC_OFFLINE); 5198 } 5199 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5200 "fca_port_manage: GET_BOOT_STATE"); 5201 5202 if (pm->pm_stat_len < sizeof (uint32_t)) { 5203 ret = FC_NOMEM; 5204 break; 5205 } 5206 bzero(pm->pm_stat_buf, pm->pm_stat_len); 5207 5208 ret = emlxs_boot_code_state(hba); 5209 5210 if (ret == FC_SUCCESS) { 5211 *(uint32_t *)pm->pm_stat_buf = 1; 5212 ret = FC_SUCCESS; 5213 } else if (ret == FC_FAILURE) { 5214 ret = FC_SUCCESS; 5215 } 5216 5217 break; 5218 } 5219 5220 case EMLXS_HW_ERROR_TEST: 5221 { 5222 /* 5223 * This command is used for simulating HW ERROR 5224 * on SLI4 only. 5225 */ 5226 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 5227 ret = FC_INVALID_REQUEST; 5228 break; 5229 } 5230 hba->sli.sli4.flag |= EMLXS_SLI4_HW_ERROR; 5231 break; 5232 } 5233 5234 case EMLXS_MB_TIMEOUT_TEST: 5235 { 5236 if (!(hba->flag & FC_ONLINE_MODE)) { 5237 return (FC_OFFLINE); 5238 } 5239 5240 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5241 "fca_port_manage: HW_ERROR_TEST"); 5242 5243 /* Trigger a mailbox timeout */ 5244 hba->mbox_timer = hba->timer_tics; 5245 5246 break; 5247 } 5248 5249 case EMLXS_TEST_CODE: 5250 { 5251 uint32_t *cmd; 5252 5253 if (!(hba->flag & FC_ONLINE_MODE)) { 5254 return (FC_OFFLINE); 5255 } 5256 5257 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5258 "fca_port_manage: TEST_CODE"); 5259 5260 if (pm->pm_cmd_len < sizeof (uint32_t)) { 5261 EMLXS_MSGF(EMLXS_CONTEXT, 5262 &emlxs_sfs_debug_msg, 5263 "fca_port_manage: TEST_CODE. " 5264 "inbuf to small."); 5265 5266 ret = FC_BADCMD; 5267 break; 5268 } 5269 5270 cmd = (uint32_t *)pm->pm_cmd_buf; 5271 5272 ret = emlxs_test(hba, cmd[0], 5273 (pm->pm_cmd_len/sizeof (uint32_t)) - 1, &cmd[1]); 5274 5275 break; 5276 } 5277 5278 case EMLXS_BAR_IO: 5279 { 5280 uint32_t *cmd; 5281 uint32_t *datap; 5282 FCIO_Q_STAT_t *qp; 5283 clock_t time; 5284 uint32_t offset; 5285 caddr_t addr; 5286 uint32_t i; 5287 uint32_t tx_cnt; 5288 uint32_t chip_cnt; 5289 5290 cmd = (uint32_t *)pm->pm_cmd_buf; 5291 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5292 "fca_port_manage: BAR_IO %x %x %x", 5293 cmd[0], cmd[1], cmd[2]); 5294 5295 offset = cmd[1]; 5296 5297 ret = FC_SUCCESS; 5298 5299 switch (cmd[0]) { 5300 case 2: /* bar1read */ 5301 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 5302 return (FC_BADCMD); 5303 } 5304 5305 /* Registers in this range are invalid */ 5306 if ((offset >= 0x4C00) && (offset < 0x5000)) { 5307 return (FC_BADCMD); 5308 } 5309 if ((offset >= 0x5800) || (offset & 0x3)) { 5310 return (FC_BADCMD); 5311 } 5312 datap = (uint32_t *)pm->pm_stat_buf; 5313 5314 for (i = 0; i < pm->pm_stat_len; 5315 i += sizeof (uint32_t)) { 5316 if ((offset >= 0x4C00) && 5317 (offset < 0x5000)) { 5318 pm->pm_stat_len = i; 5319 break; 5320 } 5321 if (offset >= 0x5800) { 5322 pm->pm_stat_len = i; 5323 break; 5324 } 5325 addr = hba->sli.sli4.bar1_addr + offset; 5326 *datap = READ_BAR1_REG(hba, addr); 5327 datap++; 5328 offset += sizeof (uint32_t); 5329 } 5330 #ifdef FMA_SUPPORT 5331 /* Access handle validation */ 5332 EMLXS_CHK_ACC_HANDLE(hba, 5333 hba->sli.sli4.bar1_acc_handle); 5334 #endif /* FMA_SUPPORT */ 5335 break; 5336 case 3: /* bar2read */ 5337 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 5338 return (FC_BADCMD); 5339 } 5340 if ((offset >= 0x1000) || (offset & 0x3)) { 5341 return (FC_BADCMD); 5342 } 5343 datap = (uint32_t *)pm->pm_stat_buf; 5344 5345 for (i = 0; i < pm->pm_stat_len; 5346 i += sizeof (uint32_t)) { 5347 *datap = READ_BAR2_REG(hba, 5348 hba->sli.sli4.bar2_addr + offset); 5349 datap++; 5350 offset += sizeof (uint32_t); 5351 } 5352 #ifdef FMA_SUPPORT 5353 /* Access handle validation */ 5354 EMLXS_CHK_ACC_HANDLE(hba, 5355 hba->sli.sli4.bar2_acc_handle); 5356 #endif /* FMA_SUPPORT */ 5357 break; 5358 case 4: /* bar1write */ 5359 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 5360 return (FC_BADCMD); 5361 } 5362 WRITE_BAR1_REG(hba, hba->sli.sli4.bar1_addr + 5363 offset, cmd[2]); 5364 #ifdef FMA_SUPPORT 5365 /* Access handle validation */ 5366 EMLXS_CHK_ACC_HANDLE(hba, 5367 hba->sli.sli4.bar1_acc_handle); 5368 #endif /* FMA_SUPPORT */ 5369 break; 5370 case 5: /* bar2write */ 5371 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 5372 return (FC_BADCMD); 5373 } 5374 WRITE_BAR2_REG(hba, hba->sli.sli4.bar2_addr + 5375 offset, cmd[2]); 5376 #ifdef FMA_SUPPORT 5377 /* Access handle validation */ 5378 EMLXS_CHK_ACC_HANDLE(hba, 5379 hba->sli.sli4.bar2_acc_handle); 5380 #endif /* FMA_SUPPORT */ 5381 break; 5382 case 6: /* dumpbsmbox */ 5383 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 5384 return (FC_BADCMD); 5385 } 5386 if (offset != 0) { 5387 return (FC_BADCMD); 5388 } 5389 5390 bcopy((caddr_t)hba->sli.sli4.bootstrapmb.virt, 5391 (caddr_t)pm->pm_stat_buf, 256); 5392 break; 5393 case 7: /* pciread */ 5394 if ((offset >= 0x200) || (offset & 0x3)) { 5395 return (FC_BADCMD); 5396 } 5397 datap = (uint32_t *)pm->pm_stat_buf; 5398 for (i = 0; i < pm->pm_stat_len; 5399 i += sizeof (uint32_t)) { 5400 *datap = ddi_get32(hba->pci_acc_handle, 5401 (uint32_t *)(hba->pci_addr + 5402 offset)); 5403 datap++; 5404 offset += sizeof (uint32_t); 5405 } 5406 #ifdef FMA_SUPPORT 5407 /* Access handle validation */ 5408 EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle); 5409 #endif /* FMA_SUPPORT */ 5410 break; 5411 case 8: /* abortall */ 5412 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 5413 return (FC_BADCMD); 5414 } 5415 emlxs_abort_all(hba, &tx_cnt, &chip_cnt); 5416 datap = (uint32_t *)pm->pm_stat_buf; 5417 *datap++ = tx_cnt; 5418 *datap = chip_cnt; 5419 break; 5420 case 9: /* get_q_info */ 5421 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 5422 return (FC_BADCMD); 5423 } 5424 qp = (FCIO_Q_STAT_t *)pm->pm_stat_buf; 5425 for (i = 0; i < FCIO_MAX_EQS; i++) { 5426 addr = hba->sli.sli4.eq[i].addr.virt; 5427 qp->eq[i].host_index = 5428 hba->sli.sli4.eq[i].host_index; 5429 qp->eq[i].max_index = 5430 hba->sli.sli4.eq[i].max_index; 5431 qp->eq[i].qid = 5432 hba->sli.sli4.eq[i].qid; 5433 qp->eq[i].msix_vector = 5434 hba->sli.sli4.eq[i].msix_vector; 5435 qp->eq[i].phys = 5436 hba->sli.sli4.eq[i].addr.phys; 5437 qp->eq[i].virt = PADDR_LO( 5438 (uintptr_t)addr); 5439 qp->eq[i].virt_hi = PADDR_HI( 5440 (uintptr_t)addr); 5441 qp->eq[i].max_proc = 5442 hba->sli.sli4.eq[i].max_proc; 5443 qp->eq[i].isr_count = 5444 hba->sli.sli4.eq[i].isr_count; 5445 qp->eq[i].num_proc = 5446 hba->sli.sli4.eq[i].num_proc; 5447 } 5448 for (i = 0; i < FCIO_MAX_CQS; i++) { 5449 addr = hba->sli.sli4.cq[i].addr.virt; 5450 qp->cq[i].host_index = 5451 hba->sli.sli4.cq[i].host_index; 5452 qp->cq[i].max_index = 5453 hba->sli.sli4.cq[i].max_index; 5454 qp->cq[i].qid = 5455 hba->sli.sli4.cq[i].qid; 5456 qp->cq[i].eqid = 5457 hba->sli.sli4.cq[i].eqid; 5458 qp->cq[i].type = 5459 hba->sli.sli4.cq[i].type; 5460 qp->cq[i].phys = 5461 hba->sli.sli4.cq[i].addr.phys; 5462 qp->cq[i].virt = PADDR_LO( 5463 (uintptr_t)addr); 5464 qp->cq[i].virt_hi = PADDR_HI( 5465 (uintptr_t)addr); 5466 qp->cq[i].max_proc = 5467 hba->sli.sli4.cq[i].max_proc; 5468 qp->cq[i].isr_count = 5469 hba->sli.sli4.cq[i].isr_count; 5470 qp->cq[i].num_proc = 5471 hba->sli.sli4.cq[i].num_proc; 5472 } 5473 for (i = 0; i < FCIO_MAX_WQS; i++) { 5474 addr = hba->sli.sli4.wq[i].addr.virt; 5475 qp->wq[i].host_index = 5476 hba->sli.sli4.wq[i].host_index; 5477 qp->wq[i].max_index = 5478 hba->sli.sli4.wq[i].max_index; 5479 qp->wq[i].port_index = 5480 hba->sli.sli4.wq[i].port_index; 5481 qp->wq[i].release_depth = 5482 hba->sli.sli4.wq[i].release_depth; 5483 qp->wq[i].qid = 5484 hba->sli.sli4.wq[i].qid; 5485 qp->wq[i].cqid = 5486 hba->sli.sli4.wq[i].cqid; 5487 qp->wq[i].phys = 5488 hba->sli.sli4.wq[i].addr.phys; 5489 qp->wq[i].virt = PADDR_LO( 5490 (uintptr_t)addr); 5491 qp->wq[i].virt_hi = PADDR_HI( 5492 (uintptr_t)addr); 5493 qp->wq[i].num_proc = 5494 hba->sli.sli4.wq[i].num_proc; 5495 qp->wq[i].num_busy = 5496 hba->sli.sli4.wq[i].num_busy; 5497 } 5498 for (i = 0; i < FCIO_MAX_RQS; i++) { 5499 addr = hba->sli.sli4.rq[i].addr.virt; 5500 qp->rq[i].qid = 5501 hba->sli.sli4.rq[i].qid; 5502 qp->rq[i].cqid = 5503 hba->sli.sli4.rq[i].cqid; 5504 qp->rq[i].host_index = 5505 hba->sli.sli4.rq[i].host_index; 5506 qp->rq[i].max_index = 5507 hba->sli.sli4.rq[i].max_index; 5508 qp->rq[i].phys = 5509 hba->sli.sli4.rq[i].addr.phys; 5510 qp->rq[i].virt = PADDR_LO( 5511 (uintptr_t)addr); 5512 qp->rq[i].virt_hi = PADDR_HI( 5513 (uintptr_t)addr); 5514 qp->rq[i].num_proc = 5515 hba->sli.sli4.rq[i].num_proc; 5516 } 5517 qp->que_start_timer = 5518 hba->sli.sli4.que_stat_timer; 5519 (void) drv_getparm(LBOLT, &time); 5520 qp->que_current_timer = (uint32_t)time; 5521 qp->intr_count = hba->intr_count; 5522 break; 5523 case 10: /* zero_q_stat */ 5524 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 5525 return (FC_BADCMD); 5526 } 5527 emlxs_sli4_zero_queue_stat(hba); 5528 break; 5529 default: 5530 ret = FC_BADCMD; 5531 break; 5532 } 5533 break; 5534 } 5535 5536 default: 5537 5538 ret = FC_INVALID_REQUEST; 5539 break; 5540 } 5541 5542 break; 5543 5544 } 5545 5546 case FC_PORT_INITIALIZE: 5547 if (!(hba->flag & FC_ONLINE_MODE)) { 5548 return (FC_OFFLINE); 5549 } 5550 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5551 "fca_port_manage: FC_PORT_INITIALIZE"); 5552 break; 5553 5554 case FC_PORT_LOOPBACK: 5555 if (!(hba->flag & FC_ONLINE_MODE)) { 5556 return (FC_OFFLINE); 5557 } 5558 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5559 "fca_port_manage: FC_PORT_LOOPBACK"); 5560 break; 5561 5562 case FC_PORT_BYPASS: 5563 if (!(hba->flag & FC_ONLINE_MODE)) { 5564 return (FC_OFFLINE); 5565 } 5566 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5567 "fca_port_manage: FC_PORT_BYPASS"); 5568 ret = FC_INVALID_REQUEST; 5569 break; 5570 5571 case FC_PORT_UNBYPASS: 5572 if (!(hba->flag & FC_ONLINE_MODE)) { 5573 return (FC_OFFLINE); 5574 } 5575 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5576 "fca_port_manage: FC_PORT_UNBYPASS"); 5577 ret = FC_INVALID_REQUEST; 5578 break; 5579 5580 case FC_PORT_GET_NODE_ID: 5581 { 5582 fc_rnid_t *rnid; 5583 5584 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5585 "fca_port_manage: FC_PORT_GET_NODE_ID"); 5586 5587 bzero(pm->pm_data_buf, pm->pm_data_len); 5588 5589 if (pm->pm_data_len < sizeof (fc_rnid_t)) { 5590 ret = FC_NOMEM; 5591 break; 5592 } 5593 5594 rnid = (fc_rnid_t *)pm->pm_data_buf; 5595 5596 (void) snprintf((char *)rnid->global_id, 5597 (sizeof (rnid->global_id)-1), 5598 "%01x%01x%02x%02x%02x%02x%02x%02x%02x", 5599 hba->wwpn.nameType, hba->wwpn.IEEEextMsn, 5600 hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0], 5601 hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3], 5602 hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 5603 5604 rnid->unit_type = RNID_HBA; 5605 rnid->port_id = port->did; 5606 rnid->ip_version = RNID_IPV4; 5607 5608 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5609 "GET_NODE_ID: wwpn: %s", rnid->global_id); 5610 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5611 "GET_NODE_ID: unit_type: 0x%x", rnid->unit_type); 5612 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5613 "GET_NODE_ID: port_id: 0x%x", rnid->port_id); 5614 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5615 "GET_NODE_ID: num_attach: %d", rnid->num_attached); 5616 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5617 "GET_NODE_ID: ip_version: 0x%x", rnid->ip_version); 5618 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5619 "GET_NODE_ID: udp_port: 0x%x", rnid->udp_port); 5620 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5621 "GET_NODE_ID: ip_addr: %s", rnid->ip_addr); 5622 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5623 "GET_NODE_ID: resv: 0x%x", rnid->specific_id_resv); 5624 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5625 "GET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags); 5626 5627 ret = FC_SUCCESS; 5628 break; 5629 } 5630 5631 case FC_PORT_SET_NODE_ID: 5632 { 5633 fc_rnid_t *rnid; 5634 5635 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5636 "fca_port_manage: FC_PORT_SET_NODE_ID"); 5637 5638 if (pm->pm_data_len < sizeof (fc_rnid_t)) { 5639 ret = FC_NOMEM; 5640 break; 5641 } 5642 5643 rnid = (fc_rnid_t *)pm->pm_data_buf; 5644 5645 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5646 "SET_NODE_ID: wwpn: %s", rnid->global_id); 5647 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5648 "SET_NODE_ID: unit_type: 0x%x", rnid->unit_type); 5649 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5650 "SET_NODE_ID: port_id: 0x%x", rnid->port_id); 5651 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5652 "SET_NODE_ID: num_attach: %d", rnid->num_attached); 5653 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5654 "SET_NODE_ID: ip_version: 0x%x", rnid->ip_version); 5655 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5656 "SET_NODE_ID: udp_port: 0x%x", rnid->udp_port); 5657 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5658 "SET_NODE_ID: ip_addr: %s", rnid->ip_addr); 5659 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5660 "SET_NODE_ID: resv: 0x%x", rnid->specific_id_resv); 5661 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5662 "SET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags); 5663 5664 ret = FC_SUCCESS; 5665 break; 5666 } 5667 5668 #ifdef S11 5669 case FC_PORT_GET_P2P_INFO: 5670 { 5671 fc_fca_p2p_info_t *p2p_info; 5672 NODELIST *ndlp; 5673 5674 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5675 "fca_port_manage: FC_PORT_GET_P2P_INFO"); 5676 5677 bzero(pm->pm_data_buf, pm->pm_data_len); 5678 5679 if (pm->pm_data_len < sizeof (fc_fca_p2p_info_t)) { 5680 ret = FC_NOMEM; 5681 break; 5682 } 5683 5684 p2p_info = (fc_fca_p2p_info_t *)pm->pm_data_buf; 5685 5686 if (hba->state >= FC_LINK_UP) { 5687 if ((hba->topology == TOPOLOGY_PT_PT) && 5688 (hba->flag & FC_PT_TO_PT)) { 5689 p2p_info->fca_d_id = port->did; 5690 p2p_info->d_id = port->rdid; 5691 5692 ndlp = emlxs_node_find_did(port, 5693 port->rdid, 1); 5694 5695 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5696 "FC_PORT_GET_P2P_INFO: fca_d_id: 0x%x, " 5697 "d_id: 0x%x, ndlp: 0x%p", port->did, 5698 port->rdid, ndlp); 5699 if (ndlp) { 5700 bcopy(&ndlp->nlp_portname, 5701 (caddr_t)&p2p_info->pwwn, 5702 sizeof (la_wwn_t)); 5703 bcopy(&ndlp->nlp_nodename, 5704 (caddr_t)&p2p_info->nwwn, 5705 sizeof (la_wwn_t)); 5706 5707 ret = FC_SUCCESS; 5708 break; 5709 5710 } 5711 } 5712 } 5713 5714 ret = FC_FAILURE; 5715 break; 5716 } 5717 #endif /* S11 */ 5718 5719 default: 5720 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5721 "fca_port_manage: code=%x", pm->pm_cmd_code); 5722 ret = FC_INVALID_REQUEST; 5723 break; 5724 5725 } 5726 5727 return (ret); 5728 5729 } /* emlxs_fca_port_manage() */ 5730 5731 5732 /*ARGSUSED*/ 5733 static uint32_t 5734 emlxs_test(emlxs_hba_t *hba, uint32_t test_code, uint32_t args, 5735 uint32_t *arg) 5736 { 5737 uint32_t rval = 0; 5738 emlxs_port_t *port = &PPORT; 5739 5740 switch (test_code) { 5741 #ifdef TEST_SUPPORT 5742 case 1: /* SCSI underrun */ 5743 { 5744 hba->underrun_counter = (args)? arg[0]:1; 5745 break; 5746 } 5747 #endif /* TEST_SUPPORT */ 5748 5749 default: 5750 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5751 "test: Unsupported test code. (0x%x)", test_code); 5752 rval = FC_INVALID_REQUEST; 5753 } 5754 5755 return (rval); 5756 5757 } /* emlxs_test() */ 5758 5759 5760 /* 5761 * Given the device number, return the devinfo pointer or the ddiinst number. 5762 * Note: this routine must be successful on DDI_INFO_DEVT2INSTANCE even 5763 * before attach. 5764 * 5765 * Translate "dev_t" to a pointer to the associated "dev_info_t". 5766 */ 5767 /*ARGSUSED*/ 5768 static int 5769 emlxs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 5770 { 5771 emlxs_hba_t *hba; 5772 int32_t ddiinst; 5773 5774 ddiinst = getminor((dev_t)arg); 5775 5776 switch (infocmd) { 5777 case DDI_INFO_DEVT2DEVINFO: 5778 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5779 if (hba) 5780 *result = hba->dip; 5781 else 5782 *result = NULL; 5783 break; 5784 5785 case DDI_INFO_DEVT2INSTANCE: 5786 *result = (void *)((unsigned long)ddiinst); 5787 break; 5788 5789 default: 5790 return (DDI_FAILURE); 5791 } 5792 5793 return (DDI_SUCCESS); 5794 5795 } /* emlxs_info() */ 5796 5797 5798 static int32_t 5799 emlxs_power(dev_info_t *dip, int32_t comp, int32_t level) 5800 { 5801 emlxs_hba_t *hba; 5802 emlxs_port_t *port; 5803 int32_t ddiinst; 5804 int rval = DDI_SUCCESS; 5805 5806 ddiinst = ddi_get_instance(dip); 5807 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5808 port = &PPORT; 5809 5810 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5811 "fca_power: comp=%x level=%x", comp, level); 5812 5813 if (hba == NULL || comp != EMLXS_PM_ADAPTER) { 5814 return (DDI_FAILURE); 5815 } 5816 5817 mutex_enter(&EMLXS_PM_LOCK); 5818 5819 /* If we are already at the proper level then return success */ 5820 if (hba->pm_level == level) { 5821 mutex_exit(&EMLXS_PM_LOCK); 5822 return (DDI_SUCCESS); 5823 } 5824 5825 switch (level) { 5826 case EMLXS_PM_ADAPTER_UP: 5827 5828 /* 5829 * If we are already in emlxs_attach, 5830 * let emlxs_hba_attach take care of things 5831 */ 5832 if (hba->pm_state & EMLXS_PM_IN_ATTACH) { 5833 hba->pm_level = EMLXS_PM_ADAPTER_UP; 5834 break; 5835 } 5836 5837 /* Check if adapter is suspended */ 5838 if (hba->pm_state & EMLXS_PM_SUSPENDED) { 5839 hba->pm_level = EMLXS_PM_ADAPTER_UP; 5840 5841 /* Try to resume the port */ 5842 rval = emlxs_hba_resume(dip); 5843 5844 if (rval != DDI_SUCCESS) { 5845 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 5846 } 5847 break; 5848 } 5849 5850 /* Set adapter up */ 5851 hba->pm_level = EMLXS_PM_ADAPTER_UP; 5852 break; 5853 5854 case EMLXS_PM_ADAPTER_DOWN: 5855 5856 5857 /* 5858 * If we are already in emlxs_detach, 5859 * let emlxs_hba_detach take care of things 5860 */ 5861 if (hba->pm_state & EMLXS_PM_IN_DETACH) { 5862 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 5863 break; 5864 } 5865 5866 /* Check if adapter is not suspended */ 5867 if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) { 5868 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 5869 5870 /* Try to suspend the port */ 5871 rval = emlxs_hba_suspend(dip); 5872 5873 if (rval != DDI_SUCCESS) { 5874 hba->pm_level = EMLXS_PM_ADAPTER_UP; 5875 } 5876 5877 break; 5878 } 5879 5880 /* Set adapter down */ 5881 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 5882 break; 5883 5884 default: 5885 rval = DDI_FAILURE; 5886 break; 5887 5888 } 5889 5890 mutex_exit(&EMLXS_PM_LOCK); 5891 5892 return (rval); 5893 5894 } /* emlxs_power() */ 5895 5896 5897 #ifdef EMLXS_I386 5898 #ifdef S11 5899 /* 5900 * quiesce(9E) entry point. 5901 * 5902 * This function is called when the system is single-thread at hight PIL 5903 * with preemption disabled. Therefore, this function must not be blocked. 5904 * 5905 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 5906 * DDI_FAILURE indicates an error condition and should almost never happen. 5907 */ 5908 static int 5909 emlxs_quiesce(dev_info_t *dip) 5910 { 5911 emlxs_hba_t *hba; 5912 emlxs_port_t *port; 5913 int32_t ddiinst; 5914 int rval = DDI_SUCCESS; 5915 5916 ddiinst = ddi_get_instance(dip); 5917 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5918 port = &PPORT; 5919 5920 if (hba == NULL || port == NULL) { 5921 return (DDI_FAILURE); 5922 } 5923 5924 /* The fourth arg 1 indicates the call is from quiesce */ 5925 if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 1) == 0) { 5926 return (rval); 5927 } else { 5928 return (DDI_FAILURE); 5929 } 5930 5931 } /* emlxs_quiesce */ 5932 #endif /* S11 */ 5933 #endif /* EMLXS_I386 */ 5934 5935 5936 static int 5937 emlxs_open(dev_t *dev_p, int32_t flag, int32_t otype, cred_t *cred_p) 5938 { 5939 emlxs_hba_t *hba; 5940 emlxs_port_t *port; 5941 int ddiinst; 5942 5943 ddiinst = getminor(*dev_p); 5944 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5945 5946 if (hba == NULL) { 5947 return (ENXIO); 5948 } 5949 5950 port = &PPORT; 5951 5952 if (hba->pm_state & EMLXS_PM_SUSPENDED) { 5953 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg, 5954 "open failed: Driver suspended."); 5955 return (ENXIO); 5956 } 5957 5958 if (otype != OTYP_CHR) { 5959 return (EINVAL); 5960 } 5961 5962 if (drv_priv(cred_p)) { 5963 return (EPERM); 5964 } 5965 5966 mutex_enter(&EMLXS_IOCTL_LOCK); 5967 5968 if (hba->ioctl_flags & EMLXS_OPEN_EXCLUSIVE) { 5969 mutex_exit(&EMLXS_IOCTL_LOCK); 5970 return (EBUSY); 5971 } 5972 5973 if (flag & FEXCL) { 5974 if (hba->ioctl_flags & EMLXS_OPEN) { 5975 mutex_exit(&EMLXS_IOCTL_LOCK); 5976 return (EBUSY); 5977 } 5978 5979 hba->ioctl_flags |= EMLXS_OPEN_EXCLUSIVE; 5980 } 5981 5982 hba->ioctl_flags |= EMLXS_OPEN; 5983 5984 mutex_exit(&EMLXS_IOCTL_LOCK); 5985 5986 return (0); 5987 5988 } /* emlxs_open() */ 5989 5990 5991 /*ARGSUSED*/ 5992 static int 5993 emlxs_close(dev_t dev, int32_t flag, int32_t otype, cred_t *cred_p) 5994 { 5995 emlxs_hba_t *hba; 5996 int ddiinst; 5997 5998 ddiinst = getminor(dev); 5999 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 6000 6001 if (hba == NULL) { 6002 return (ENXIO); 6003 } 6004 6005 if (otype != OTYP_CHR) { 6006 return (EINVAL); 6007 } 6008 6009 mutex_enter(&EMLXS_IOCTL_LOCK); 6010 6011 if (!(hba->ioctl_flags & EMLXS_OPEN)) { 6012 mutex_exit(&EMLXS_IOCTL_LOCK); 6013 return (ENODEV); 6014 } 6015 6016 hba->ioctl_flags &= ~EMLXS_OPEN; 6017 hba->ioctl_flags &= ~EMLXS_OPEN_EXCLUSIVE; 6018 6019 mutex_exit(&EMLXS_IOCTL_LOCK); 6020 6021 return (0); 6022 6023 } /* emlxs_close() */ 6024 6025 6026 /*ARGSUSED*/ 6027 static int 6028 emlxs_ioctl(dev_t dev, int32_t cmd, intptr_t arg, int32_t mode, 6029 cred_t *cred_p, int32_t *rval_p) 6030 { 6031 emlxs_hba_t *hba; 6032 emlxs_port_t *port; 6033 int rval = 0; /* return code */ 6034 int ddiinst; 6035 6036 ddiinst = getminor(dev); 6037 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 6038 6039 if (hba == NULL) { 6040 return (ENXIO); 6041 } 6042 6043 port = &PPORT; 6044 6045 if (hba->pm_state & EMLXS_PM_SUSPENDED) { 6046 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg, 6047 "ioctl failed: Driver suspended."); 6048 6049 return (ENXIO); 6050 } 6051 6052 mutex_enter(&EMLXS_IOCTL_LOCK); 6053 if (!(hba->ioctl_flags & EMLXS_OPEN)) { 6054 mutex_exit(&EMLXS_IOCTL_LOCK); 6055 return (ENXIO); 6056 } 6057 mutex_exit(&EMLXS_IOCTL_LOCK); 6058 6059 #ifdef IDLE_TIMER 6060 emlxs_pm_busy_component(hba); 6061 #endif /* IDLE_TIMER */ 6062 6063 switch (cmd) { 6064 case EMLXS_DFC_COMMAND: 6065 rval = emlxs_dfc_manage(hba, (void *)arg, mode); 6066 break; 6067 6068 default: 6069 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg, 6070 "ioctl: Invalid command received. cmd=%x", cmd); 6071 rval = EINVAL; 6072 } 6073 6074 done: 6075 return (rval); 6076 6077 } /* emlxs_ioctl() */ 6078 6079 6080 6081 /* 6082 * 6083 * Device Driver Common Routines 6084 * 6085 */ 6086 6087 /* EMLXS_PM_LOCK must be held for this call */ 6088 static int 6089 emlxs_hba_resume(dev_info_t *dip) 6090 { 6091 emlxs_hba_t *hba; 6092 emlxs_port_t *port; 6093 int ddiinst; 6094 6095 ddiinst = ddi_get_instance(dip); 6096 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 6097 port = &PPORT; 6098 6099 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_msg, NULL); 6100 6101 if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) { 6102 return (DDI_SUCCESS); 6103 } 6104 6105 hba->pm_state &= ~EMLXS_PM_SUSPENDED; 6106 6107 /* Re-enable the physical port on this HBA */ 6108 port->flag |= EMLXS_PORT_ENABLED; 6109 6110 /* Take the adapter online */ 6111 if (emlxs_power_up(hba)) { 6112 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_failed_msg, 6113 "Unable to take adapter online."); 6114 6115 hba->pm_state |= EMLXS_PM_SUSPENDED; 6116 6117 return (DDI_FAILURE); 6118 } 6119 6120 return (DDI_SUCCESS); 6121 6122 } /* emlxs_hba_resume() */ 6123 6124 6125 /* EMLXS_PM_LOCK must be held for this call */ 6126 static int 6127 emlxs_hba_suspend(dev_info_t *dip) 6128 { 6129 emlxs_hba_t *hba; 6130 emlxs_port_t *port; 6131 int ddiinst; 6132 6133 ddiinst = ddi_get_instance(dip); 6134 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 6135 port = &PPORT; 6136 6137 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_msg, NULL); 6138 6139 if (hba->pm_state & EMLXS_PM_SUSPENDED) { 6140 return (DDI_SUCCESS); 6141 } 6142 6143 hba->pm_state |= EMLXS_PM_SUSPENDED; 6144 6145 /* Take the adapter offline */ 6146 if (emlxs_power_down(hba)) { 6147 hba->pm_state &= ~EMLXS_PM_SUSPENDED; 6148 6149 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_failed_msg, 6150 "Unable to take adapter offline."); 6151 6152 return (DDI_FAILURE); 6153 } 6154 6155 return (DDI_SUCCESS); 6156 6157 } /* emlxs_hba_suspend() */ 6158 6159 6160 6161 static void 6162 emlxs_lock_init(emlxs_hba_t *hba) 6163 { 6164 emlxs_port_t *port = &PPORT; 6165 uint32_t i; 6166 6167 /* Initialize the power management */ 6168 mutex_init(&EMLXS_PM_LOCK, NULL, MUTEX_DRIVER, 6169 DDI_INTR_PRI(hba->intr_arg)); 6170 6171 mutex_init(&EMLXS_TIMER_LOCK, NULL, MUTEX_DRIVER, 6172 DDI_INTR_PRI(hba->intr_arg)); 6173 6174 cv_init(&hba->timer_lock_cv, NULL, CV_DRIVER, NULL); 6175 6176 mutex_init(&EMLXS_PORT_LOCK, NULL, MUTEX_DRIVER, 6177 DDI_INTR_PRI(hba->intr_arg)); 6178 6179 mutex_init(&EMLXS_MBOX_LOCK, NULL, MUTEX_DRIVER, 6180 DDI_INTR_PRI(hba->intr_arg)); 6181 6182 cv_init(&EMLXS_MBOX_CV, NULL, CV_DRIVER, NULL); 6183 6184 mutex_init(&EMLXS_LINKUP_LOCK, NULL, MUTEX_DRIVER, 6185 DDI_INTR_PRI(hba->intr_arg)); 6186 6187 cv_init(&EMLXS_LINKUP_CV, NULL, CV_DRIVER, NULL); 6188 6189 mutex_init(&EMLXS_TX_CHANNEL_LOCK, NULL, MUTEX_DRIVER, 6190 DDI_INTR_PRI(hba->intr_arg)); 6191 6192 for (i = 0; i < MAX_RINGS; i++) { 6193 mutex_init(&EMLXS_CMD_RING_LOCK(i), NULL, MUTEX_DRIVER, 6194 DDI_INTR_PRI(hba->intr_arg)); 6195 } 6196 6197 6198 for (i = 0; i < EMLXS_MAX_WQS; i++) { 6199 mutex_init(&EMLXS_QUE_LOCK(i), NULL, MUTEX_DRIVER, 6200 DDI_INTR_PRI(hba->intr_arg)); 6201 } 6202 6203 mutex_init(&EMLXS_MSIID_LOCK, NULL, MUTEX_DRIVER, 6204 DDI_INTR_PRI(hba->intr_arg)); 6205 6206 mutex_init(&EMLXS_FCTAB_LOCK, NULL, MUTEX_DRIVER, 6207 DDI_INTR_PRI(hba->intr_arg)); 6208 6209 mutex_init(&EMLXS_MEMGET_LOCK, NULL, MUTEX_DRIVER, 6210 DDI_INTR_PRI(hba->intr_arg)); 6211 6212 mutex_init(&EMLXS_MEMPUT_LOCK, NULL, MUTEX_DRIVER, 6213 DDI_INTR_PRI(hba->intr_arg)); 6214 6215 mutex_init(&EMLXS_IOCTL_LOCK, NULL, MUTEX_DRIVER, 6216 DDI_INTR_PRI(hba->intr_arg)); 6217 6218 #ifdef DUMP_SUPPORT 6219 mutex_init(&EMLXS_DUMP_LOCK, NULL, MUTEX_DRIVER, 6220 DDI_INTR_PRI(hba->intr_arg)); 6221 #endif /* DUMP_SUPPORT */ 6222 6223 mutex_init(&EMLXS_SPAWN_LOCK, NULL, MUTEX_DRIVER, 6224 DDI_INTR_PRI(hba->intr_arg)); 6225 6226 /* Create per port locks */ 6227 for (i = 0; i < MAX_VPORTS; i++) { 6228 port = &VPORT(i); 6229 6230 rw_init(&port->node_rwlock, NULL, RW_DRIVER, NULL); 6231 6232 if (i == 0) { 6233 mutex_init(&EMLXS_PKT_LOCK, NULL, MUTEX_DRIVER, 6234 DDI_INTR_PRI(hba->intr_arg)); 6235 6236 cv_init(&EMLXS_PKT_CV, NULL, CV_DRIVER, NULL); 6237 6238 mutex_init(&EMLXS_UB_LOCK, NULL, MUTEX_DRIVER, 6239 DDI_INTR_PRI(hba->intr_arg)); 6240 } else { 6241 mutex_init(&EMLXS_PKT_LOCK, NULL, MUTEX_DRIVER, 6242 DDI_INTR_PRI(hba->intr_arg)); 6243 6244 cv_init(&EMLXS_PKT_CV, NULL, CV_DRIVER, NULL); 6245 6246 mutex_init(&EMLXS_UB_LOCK, NULL, MUTEX_DRIVER, 6247 DDI_INTR_PRI(hba->intr_arg)); 6248 } 6249 } 6250 6251 return; 6252 6253 } /* emlxs_lock_init() */ 6254 6255 6256 6257 static void 6258 emlxs_lock_destroy(emlxs_hba_t *hba) 6259 { 6260 emlxs_port_t *port = &PPORT; 6261 uint32_t i; 6262 6263 mutex_destroy(&EMLXS_TIMER_LOCK); 6264 cv_destroy(&hba->timer_lock_cv); 6265 6266 mutex_destroy(&EMLXS_PORT_LOCK); 6267 6268 cv_destroy(&EMLXS_MBOX_CV); 6269 cv_destroy(&EMLXS_LINKUP_CV); 6270 6271 mutex_destroy(&EMLXS_LINKUP_LOCK); 6272 mutex_destroy(&EMLXS_MBOX_LOCK); 6273 6274 mutex_destroy(&EMLXS_TX_CHANNEL_LOCK); 6275 6276 for (i = 0; i < MAX_RINGS; i++) { 6277 mutex_destroy(&EMLXS_CMD_RING_LOCK(i)); 6278 } 6279 6280 for (i = 0; i < EMLXS_MAX_WQS; i++) { 6281 mutex_destroy(&EMLXS_QUE_LOCK(i)); 6282 } 6283 6284 mutex_destroy(&EMLXS_MSIID_LOCK); 6285 6286 mutex_destroy(&EMLXS_FCTAB_LOCK); 6287 mutex_destroy(&EMLXS_MEMGET_LOCK); 6288 mutex_destroy(&EMLXS_MEMPUT_LOCK); 6289 mutex_destroy(&EMLXS_IOCTL_LOCK); 6290 mutex_destroy(&EMLXS_SPAWN_LOCK); 6291 mutex_destroy(&EMLXS_PM_LOCK); 6292 6293 #ifdef DUMP_SUPPORT 6294 mutex_destroy(&EMLXS_DUMP_LOCK); 6295 #endif /* DUMP_SUPPORT */ 6296 6297 /* Destroy per port locks */ 6298 for (i = 0; i < MAX_VPORTS; i++) { 6299 port = &VPORT(i); 6300 rw_destroy(&port->node_rwlock); 6301 mutex_destroy(&EMLXS_PKT_LOCK); 6302 cv_destroy(&EMLXS_PKT_CV); 6303 mutex_destroy(&EMLXS_UB_LOCK); 6304 } 6305 6306 return; 6307 6308 } /* emlxs_lock_destroy() */ 6309 6310 6311 /* init_flag values */ 6312 #define ATTACH_SOFT_STATE 0x00000001 6313 #define ATTACH_FCA_TRAN 0x00000002 6314 #define ATTACH_HBA 0x00000004 6315 #define ATTACH_LOG 0x00000008 6316 #define ATTACH_MAP_BUS 0x00000010 6317 #define ATTACH_INTR_INIT 0x00000020 6318 #define ATTACH_PROP 0x00000040 6319 #define ATTACH_LOCK 0x00000080 6320 #define ATTACH_THREAD 0x00000100 6321 #define ATTACH_INTR_ADD 0x00000200 6322 #define ATTACH_ONLINE 0x00000400 6323 #define ATTACH_NODE 0x00000800 6324 #define ATTACH_FCT 0x00001000 6325 #define ATTACH_FCA 0x00002000 6326 #define ATTACH_KSTAT 0x00004000 6327 #define ATTACH_DHCHAP 0x00008000 6328 #define ATTACH_FM 0x00010000 6329 #define ATTACH_MAP_SLI 0x00020000 6330 #define ATTACH_SPAWN 0x00040000 6331 #define ATTACH_EVENTS 0x00080000 6332 6333 static void 6334 emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag, uint32_t failed) 6335 { 6336 emlxs_hba_t *hba = NULL; 6337 int ddiinst; 6338 6339 ddiinst = ddi_get_instance(dip); 6340 6341 if (init_flag & ATTACH_HBA) { 6342 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 6343 6344 if (init_flag & ATTACH_SPAWN) { 6345 emlxs_thread_spawn_destroy(hba); 6346 } 6347 6348 if (init_flag & ATTACH_EVENTS) { 6349 (void) emlxs_event_queue_destroy(hba); 6350 } 6351 6352 if (init_flag & ATTACH_ONLINE) { 6353 (void) emlxs_offline(hba, 1); 6354 } 6355 6356 if (init_flag & ATTACH_INTR_ADD) { 6357 (void) EMLXS_INTR_REMOVE(hba); 6358 } 6359 #ifdef SFCT_SUPPORT 6360 if (init_flag & ATTACH_FCT) { 6361 emlxs_fct_detach(hba); 6362 emlxs_fct_modclose(); 6363 } 6364 #endif /* SFCT_SUPPORT */ 6365 6366 #ifdef DHCHAP_SUPPORT 6367 if (init_flag & ATTACH_DHCHAP) { 6368 emlxs_dhc_detach(hba); 6369 } 6370 #endif /* DHCHAP_SUPPORT */ 6371 6372 if (init_flag & ATTACH_KSTAT) { 6373 kstat_delete(hba->kstat); 6374 } 6375 6376 if (init_flag & ATTACH_FCA) { 6377 emlxs_fca_detach(hba); 6378 } 6379 6380 if (init_flag & ATTACH_NODE) { 6381 (void) ddi_remove_minor_node(hba->dip, "devctl"); 6382 } 6383 6384 if (init_flag & ATTACH_THREAD) { 6385 emlxs_thread_destroy(&hba->iodone_thread); 6386 } 6387 6388 if (init_flag & ATTACH_PROP) { 6389 (void) ddi_prop_remove_all(hba->dip); 6390 } 6391 6392 if (init_flag & ATTACH_LOCK) { 6393 emlxs_lock_destroy(hba); 6394 } 6395 6396 if (init_flag & ATTACH_INTR_INIT) { 6397 (void) EMLXS_INTR_UNINIT(hba); 6398 } 6399 6400 if (init_flag & ATTACH_MAP_BUS) { 6401 emlxs_unmap_bus(hba); 6402 } 6403 6404 if (init_flag & ATTACH_MAP_SLI) { 6405 EMLXS_SLI_UNMAP_HDW(hba); 6406 } 6407 6408 #ifdef FMA_SUPPORT 6409 if (init_flag & ATTACH_FM) { 6410 emlxs_fm_fini(hba); 6411 } 6412 #endif /* FMA_SUPPORT */ 6413 6414 if (init_flag & ATTACH_LOG) { 6415 emlxs_msg_log_destroy(hba); 6416 } 6417 6418 if (init_flag & ATTACH_FCA_TRAN) { 6419 (void) ddi_set_driver_private(hba->dip, NULL); 6420 kmem_free(hba->fca_tran, sizeof (fc_fca_tran_t)); 6421 hba->fca_tran = NULL; 6422 } 6423 6424 if (init_flag & ATTACH_HBA) { 6425 emlxs_device.log[hba->emlxinst] = 0; 6426 emlxs_device.hba[hba->emlxinst] = 6427 (emlxs_hba_t *)((unsigned long)((failed) ? -1 : 0)); 6428 #ifdef DUMP_SUPPORT 6429 emlxs_device.dump_txtfile[hba->emlxinst] = 0; 6430 emlxs_device.dump_dmpfile[hba->emlxinst] = 0; 6431 emlxs_device.dump_ceefile[hba->emlxinst] = 0; 6432 #endif /* DUMP_SUPPORT */ 6433 6434 } 6435 } 6436 6437 if (init_flag & ATTACH_SOFT_STATE) { 6438 (void) ddi_soft_state_free(emlxs_soft_state, ddiinst); 6439 } 6440 6441 return; 6442 6443 } /* emlxs_driver_remove() */ 6444 6445 6446 /* This determines which ports will be initiator mode */ 6447 static uint32_t 6448 emlxs_fca_init(emlxs_hba_t *hba) 6449 { 6450 emlxs_port_t *port = &PPORT; 6451 6452 /* Check if SFS present */ 6453 if (((void *)MODSYM(fc_fca_init) == NULL) || 6454 ((void *)MODSYM(fc_fca_attach) == NULL)) { 6455 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6456 "SFS not present."); 6457 return (1); 6458 } 6459 6460 /* Check if our SFS driver interface matches the current SFS stack */ 6461 if (MODSYM(fc_fca_attach) (hba->dip, hba->fca_tran) != DDI_SUCCESS) { 6462 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6463 "SFS/FCA version mismatch. FCA=0x%x", 6464 hba->fca_tran->fca_version); 6465 return (1); 6466 } 6467 6468 return (0); 6469 6470 } /* emlxs_fca_init() */ 6471 6472 6473 /* This determines which ports will be initiator or target mode */ 6474 static void 6475 emlxs_mode_init(emlxs_hba_t *hba) 6476 { 6477 emlxs_port_t *port = &PPORT; 6478 emlxs_config_t *cfg = &CFG; 6479 emlxs_port_t *vport; 6480 uint32_t i; 6481 uint32_t mode_mask; 6482 6483 /* Initialize mode masks */ 6484 (void) emlxs_mode_init_masks(hba); 6485 6486 if (!(port->mode_mask & MODE_INITIATOR)) { 6487 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6488 "Initiator mode not enabled."); 6489 6490 #ifdef SFCT_SUPPORT 6491 /* Disable dynamic target mode */ 6492 cfg[CFG_DTM_ENABLE].current = 0; 6493 #endif /* SFCT_SUPPORT */ 6494 6495 goto done1; 6496 } 6497 6498 /* Try to initialize fca interface */ 6499 if (emlxs_fca_init(hba) != 0) { 6500 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6501 "Initiator mode disabled."); 6502 6503 /* Disable initiator mode */ 6504 port->mode_mask &= ~MODE_INITIATOR; 6505 6506 #ifdef SFCT_SUPPORT 6507 /* Disable dynamic target mode */ 6508 cfg[CFG_DTM_ENABLE].current = 0; 6509 #endif /* SFCT_SUPPORT */ 6510 6511 goto done1; 6512 } 6513 6514 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6515 "Initiator mode enabled."); 6516 6517 done1: 6518 6519 #ifdef SFCT_SUPPORT 6520 if (!(port->mode_mask & MODE_TARGET)) { 6521 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6522 "Target mode not enabled."); 6523 6524 /* Disable target modes */ 6525 cfg[CFG_DTM_ENABLE].current = 0; 6526 cfg[CFG_TARGET_MODE].current = 0; 6527 6528 goto done2; 6529 } 6530 6531 /* Try to open the COMSTAR module */ 6532 if (emlxs_fct_modopen() != 0) { 6533 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6534 "Target mode disabled."); 6535 6536 /* Disable target modes */ 6537 port->mode_mask &= ~MODE_TARGET; 6538 cfg[CFG_DTM_ENABLE].current = 0; 6539 cfg[CFG_TARGET_MODE].current = 0; 6540 6541 goto done2; 6542 } 6543 6544 /* Try to initialize fct interface */ 6545 if (emlxs_fct_init(hba) != 0) { 6546 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6547 "Target mode disabled."); 6548 6549 /* Disable target modes */ 6550 port->mode_mask &= ~MODE_TARGET; 6551 cfg[CFG_DTM_ENABLE].current = 0; 6552 cfg[CFG_TARGET_MODE].current = 0; 6553 6554 goto done2; 6555 } 6556 6557 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6558 "Target mode enabled."); 6559 6560 done2: 6561 /* Adjust target mode parameter flags */ 6562 if (cfg[CFG_DTM_ENABLE].current) { 6563 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6564 "Dynamic target mode enabled."); 6565 6566 cfg[CFG_TARGET_MODE].flags |= PARM_DYNAMIC; 6567 } else { 6568 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6569 "Dynamic target mode disabled."); 6570 6571 cfg[CFG_TARGET_MODE].flags &= ~PARM_DYNAMIC; 6572 } 6573 #endif /* SFCT_SUPPORT */ 6574 6575 /* Now set port flags */ 6576 mutex_enter(&EMLXS_PORT_LOCK); 6577 6578 /* Set flags for physical port */ 6579 if (port->mode_mask & MODE_INITIATOR) { 6580 port->flag |= EMLXS_INI_ENABLED; 6581 } else { 6582 port->flag &= ~EMLXS_INI_ENABLED; 6583 } 6584 6585 if (port->mode_mask & MODE_TARGET) { 6586 port->flag |= EMLXS_TGT_ENABLED; 6587 } else { 6588 port->flag &= ~EMLXS_TGT_ENABLED; 6589 } 6590 6591 for (i = 1; i < MAX_VPORTS; i++) { 6592 vport = &VPORT(i); 6593 6594 /* Physical port mask has only allowable bits */ 6595 mode_mask = vport->mode_mask & port->mode_mask; 6596 6597 /* Set flags for physical port */ 6598 if (mode_mask & MODE_INITIATOR) { 6599 vport->flag |= EMLXS_INI_ENABLED; 6600 } else { 6601 vport->flag &= ~EMLXS_INI_ENABLED; 6602 } 6603 6604 if (mode_mask & MODE_TARGET) { 6605 vport->flag |= EMLXS_TGT_ENABLED; 6606 } else { 6607 vport->flag &= ~EMLXS_TGT_ENABLED; 6608 } 6609 } 6610 6611 /* Set initial driver mode */ 6612 emlxs_mode_set(hba); 6613 6614 mutex_exit(&EMLXS_PORT_LOCK); 6615 6616 /* Recheck possible mode dependent parameters */ 6617 /* in case conditions have changed. */ 6618 if (port->mode != MODE_NONE) { 6619 for (i = 0; i < NUM_CFG_PARAM; i++) { 6620 cfg = &hba->config[i]; 6621 cfg->current = emlxs_check_parm(hba, i, cfg->current); 6622 } 6623 } 6624 6625 return; 6626 6627 } /* emlxs_mode_init() */ 6628 6629 6630 /* This must be called while holding the EMLXS_PORT_LOCK */ 6631 extern void 6632 emlxs_mode_set(emlxs_hba_t *hba) 6633 { 6634 emlxs_port_t *port = &PPORT; 6635 #ifdef SFCT_SUPPORT 6636 emlxs_config_t *cfg = &CFG; 6637 #endif /* SFCT_SUPPORT */ 6638 emlxs_port_t *vport; 6639 uint32_t i; 6640 uint32_t cfg_tgt_mode = 0; 6641 6642 /* mutex_enter(&EMLXS_PORT_LOCK); */ 6643 6644 #ifdef SFCT_SUPPORT 6645 cfg_tgt_mode = cfg[CFG_TARGET_MODE].current; 6646 #endif /* SFCT_SUPPORT */ 6647 6648 /* Initiator mode requested */ 6649 if (!cfg_tgt_mode) { 6650 for (i = 0; i < MAX_VPORTS; i++) { 6651 vport = &VPORT(i); 6652 vport->mode = (vport->flag & EMLXS_INI_ENABLED)? 6653 MODE_INITIATOR:MODE_NONE; 6654 } 6655 #ifdef SFCT_SUPPORT 6656 /* Target mode requested */ 6657 } else { 6658 for (i = 0; i < MAX_VPORTS; i++) { 6659 vport = &VPORT(i); 6660 vport->mode = (vport->flag & EMLXS_TGT_ENABLED)? 6661 MODE_TARGET:MODE_NONE; 6662 } 6663 #endif /* SFCT_SUPPORT */ 6664 } 6665 6666 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 6667 "MODE: %s", emlxs_mode_xlate(port->mode)); 6668 6669 /* mutex_exit(&EMLXS_PORT_LOCK); */ 6670 6671 return; 6672 6673 } /* emlxs_mode_set() */ 6674 6675 6676 static void 6677 emlxs_mode_init_masks(emlxs_hba_t *hba) 6678 { 6679 emlxs_port_t *port = &PPORT; 6680 emlxs_port_t *vport; 6681 uint32_t i; 6682 6683 #ifdef SFCT_SUPPORT 6684 emlxs_config_t *cfg = &CFG; 6685 uint32_t vport_mode_mask; 6686 uint32_t cfg_vport_mode_mask; 6687 uint32_t mode_mask; 6688 char string[256]; 6689 6690 port->mode_mask = 0; 6691 6692 if (!cfg[CFG_TARGET_MODE].current || 6693 cfg[CFG_DTM_ENABLE].current) { 6694 port->mode_mask |= MODE_INITIATOR; 6695 } 6696 6697 if (cfg[CFG_TARGET_MODE].current || 6698 cfg[CFG_DTM_ENABLE].current) { 6699 port->mode_mask |= MODE_TARGET; 6700 } 6701 6702 /* Physical port mask has only allowable bits */ 6703 vport_mode_mask = port->mode_mask; 6704 cfg_vport_mode_mask = cfg[CFG_VPORT_MODE_MASK].current; 6705 6706 /* Check dynamic target mode value for virtual ports */ 6707 if (cfg[CFG_DTM_ENABLE].current == 0) { 6708 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6709 "%s = 0: Virtual target ports are not supported.", 6710 cfg[CFG_DTM_ENABLE].string); 6711 6712 vport_mode_mask &= ~MODE_TARGET; 6713 } 6714 6715 cfg_vport_mode_mask &= vport_mode_mask; 6716 6717 if (cfg[CFG_VPORT_MODE_MASK].current != cfg_vport_mode_mask) { 6718 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6719 "%s: Changing 0x%x --> 0x%x", 6720 cfg[CFG_VPORT_MODE_MASK].string, 6721 cfg[CFG_VPORT_MODE_MASK].current, 6722 cfg_vport_mode_mask); 6723 6724 cfg[CFG_VPORT_MODE_MASK].current = cfg_vport_mode_mask; 6725 } 6726 6727 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6728 "pport-mode-mask: %s", emlxs_mode_xlate(port->mode_mask)); 6729 6730 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6731 "vport-mode-mask: %s", emlxs_mode_xlate(cfg_vport_mode_mask)); 6732 6733 for (i = 1; i < MAX_VPORTS; i++) { 6734 vport = &VPORT(i); 6735 6736 (void) snprintf(string, sizeof (string), 6737 "%s%d-vport%d-mode-mask", DRIVER_NAME, hba->ddiinst, i); 6738 6739 mode_mask = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, 6740 (void *)hba->dip, DDI_PROP_DONTPASS, string, 6741 cfg_vport_mode_mask); 6742 6743 vport->mode_mask = mode_mask & vport_mode_mask; 6744 6745 if (vport->mode_mask != cfg_vport_mode_mask) { 6746 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6747 "vport%d-mode-mask: %s", 6748 i, emlxs_mode_xlate(vport->mode_mask)); 6749 } 6750 } 6751 #else 6752 port->mode_mask = MODE_INITIATOR; 6753 for (i = 1; i < MAX_VPORTS; i++) { 6754 vport = &VPORT(i); 6755 vport->mode_mask = MODE_INITIATOR; 6756 } 6757 #endif /* SFCT_SUPPORT */ 6758 6759 return; 6760 6761 } /* emlxs_mode_init_masks() */ 6762 6763 6764 static void 6765 emlxs_fca_attach(emlxs_hba_t *hba) 6766 { 6767 emlxs_port_t *port; 6768 uint32_t i; 6769 6770 /* Update our transport structure */ 6771 hba->fca_tran->fca_iblock = (ddi_iblock_cookie_t *)&hba->intr_arg; 6772 hba->fca_tran->fca_cmd_max = hba->io_throttle; 6773 6774 for (i = 0; i < MAX_VPORTS; i++) { 6775 port = &VPORT(i); 6776 port->ub_count = EMLXS_UB_TOKEN_OFFSET; 6777 port->ub_pool = NULL; 6778 } 6779 6780 #if (EMLXS_MODREV >= EMLXS_MODREV5) 6781 bcopy((caddr_t)&hba->wwpn, (caddr_t)&hba->fca_tran->fca_perm_pwwn, 6782 sizeof (NAME_TYPE)); 6783 #endif /* >= EMLXS_MODREV5 */ 6784 6785 return; 6786 6787 } /* emlxs_fca_attach() */ 6788 6789 6790 static void 6791 emlxs_fca_detach(emlxs_hba_t *hba) 6792 { 6793 emlxs_port_t *port = &PPORT; 6794 uint32_t i; 6795 emlxs_port_t *vport; 6796 6797 if (!(port->flag & EMLXS_INI_ENABLED)) { 6798 return; 6799 } 6800 6801 if ((void *)MODSYM(fc_fca_detach) != NULL) { 6802 MODSYM(fc_fca_detach)(hba->dip); 6803 } 6804 6805 /* Disable INI mode for all ports */ 6806 for (i = 0; i < MAX_VPORTS; i++) { 6807 vport = &VPORT(i); 6808 vport->flag &= ~EMLXS_INI_ENABLED; 6809 } 6810 6811 return; 6812 6813 } /* emlxs_fca_detach() */ 6814 6815 6816 static void 6817 emlxs_drv_banner(emlxs_hba_t *hba) 6818 { 6819 emlxs_port_t *port = &PPORT; 6820 uint32_t i; 6821 char sli_mode[16]; 6822 char msi_mode[16]; 6823 char npiv_mode[16]; 6824 emlxs_vpd_t *vpd = &VPD; 6825 uint8_t *wwpn; 6826 uint8_t *wwnn; 6827 uint32_t fw_show = 0; 6828 6829 /* Display firmware library one time for all driver instances */ 6830 mutex_enter(&emlxs_device.lock); 6831 if (!(emlxs_instance_flag & EMLXS_FW_SHOW)) { 6832 emlxs_instance_flag |= EMLXS_FW_SHOW; 6833 fw_show = 1; 6834 } 6835 mutex_exit(&emlxs_device.lock); 6836 6837 if (fw_show) { 6838 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s", 6839 emlxs_copyright); 6840 emlxs_fw_show(hba); 6841 } 6842 6843 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s (%s)", emlxs_label, 6844 emlxs_revision); 6845 6846 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 6847 "%s Dev_id:%x Sub_id:%x Id:%d", hba->model_info.model, 6848 hba->model_info.device_id, hba->model_info.ssdid, 6849 hba->model_info.id); 6850 6851 #ifdef EMLXS_I386 6852 6853 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 6854 "Firmware:%s (%s) Boot:%s", vpd->fw_version, vpd->fw_label, 6855 vpd->boot_version); 6856 6857 #else /* EMLXS_SPARC */ 6858 6859 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 6860 "Firmware:%s (%s) Boot:%s Fcode:%s", vpd->fw_version, 6861 vpd->fw_label, vpd->boot_version, vpd->fcode_version); 6862 6863 #endif /* EMLXS_I386 */ 6864 6865 if (hba->sli_mode > 3) { 6866 (void) snprintf(sli_mode, sizeof (sli_mode), "SLI:%d(%s)", 6867 hba->sli_mode, 6868 ((hba->flag & FC_FIP_SUPPORTED) ? "FIP" : "nonFIP")); 6869 } else { 6870 (void) snprintf(sli_mode, sizeof (sli_mode), "SLI:%d", 6871 hba->sli_mode); 6872 } 6873 6874 (void) strlcpy(msi_mode, " INTX:1", sizeof (msi_mode)); 6875 6876 #ifdef MSI_SUPPORT 6877 if (hba->intr_flags & EMLXS_MSI_ENABLED) { 6878 switch (hba->intr_type) { 6879 case DDI_INTR_TYPE_FIXED: 6880 (void) strlcpy(msi_mode, " MSI:0", sizeof (msi_mode)); 6881 break; 6882 6883 case DDI_INTR_TYPE_MSI: 6884 (void) snprintf(msi_mode, sizeof (msi_mode), " MSI:%d", 6885 hba->intr_count); 6886 break; 6887 6888 case DDI_INTR_TYPE_MSIX: 6889 (void) snprintf(msi_mode, sizeof (msi_mode), " MSIX:%d", 6890 hba->intr_count); 6891 break; 6892 } 6893 } 6894 #endif /* MSI_SUPPORT */ 6895 6896 (void) strlcpy(npiv_mode, "", sizeof (npiv_mode)); 6897 6898 if (hba->flag & FC_NPIV_ENABLED) { 6899 (void) snprintf(npiv_mode, sizeof (npiv_mode), " NPIV:%d", 6900 hba->vpi_max+1); 6901 } else { 6902 (void) strlcpy(npiv_mode, " NPIV:0", sizeof (npiv_mode)); 6903 } 6904 6905 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 6906 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s%s%s%s%s%s", 6907 sli_mode, msi_mode, npiv_mode, 6908 ((port->flag & EMLXS_INI_ENABLED)? " FCA":""), 6909 ((port->flag & EMLXS_TGT_ENABLED)? " FCT":""), 6910 ((SLI4_FCOE_MODE)? " FCoE":" FC")); 6911 } else { 6912 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s%s%s%s%s", 6913 sli_mode, msi_mode, npiv_mode, 6914 ((port->flag & EMLXS_INI_ENABLED)? " FCA":""), 6915 ((port->flag & EMLXS_TGT_ENABLED)? " FCT":"")); 6916 } 6917 6918 wwpn = (uint8_t *)&hba->wwpn; 6919 wwnn = (uint8_t *)&hba->wwnn; 6920 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 6921 "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X " 6922 "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X", 6923 wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6], 6924 wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3], wwnn[4], wwnn[5], 6925 wwnn[6], wwnn[7]); 6926 6927 for (i = 0; i < MAX_VPORTS; i++) { 6928 port = &VPORT(i); 6929 6930 if (!(port->flag & EMLXS_PORT_CONFIG)) { 6931 continue; 6932 } 6933 6934 wwpn = (uint8_t *)&port->wwpn; 6935 wwnn = (uint8_t *)&port->wwnn; 6936 6937 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 6938 "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X " 6939 "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X", 6940 wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5], 6941 wwpn[6], wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3], 6942 wwnn[4], wwnn[5], wwnn[6], wwnn[7]); 6943 } 6944 6945 /* 6946 * Announce the device: ddi_report_dev() prints a banner at boot time, 6947 * announcing the device pointed to by dip. 6948 */ 6949 (void) ddi_report_dev(hba->dip); 6950 6951 return; 6952 6953 } /* emlxs_drv_banner() */ 6954 6955 6956 extern void 6957 emlxs_get_fcode_version(emlxs_hba_t *hba) 6958 { 6959 emlxs_vpd_t *vpd = &VPD; 6960 char *prop_str; 6961 int status; 6962 6963 /* Setup fcode version property */ 6964 prop_str = NULL; 6965 status = 6966 ddi_prop_lookup_string(DDI_DEV_T_ANY, (dev_info_t *)hba->dip, 0, 6967 "fcode-version", (char **)&prop_str); 6968 6969 if (status == DDI_PROP_SUCCESS) { 6970 bcopy(prop_str, vpd->fcode_version, strlen(prop_str)); 6971 (void) ddi_prop_free((void *)prop_str); 6972 } else { 6973 (void) strncpy(vpd->fcode_version, "none", 6974 (sizeof (vpd->fcode_version)-1)); 6975 } 6976 6977 return; 6978 6979 } /* emlxs_get_fcode_version() */ 6980 6981 6982 static int 6983 emlxs_hba_attach(dev_info_t *dip) 6984 { 6985 emlxs_hba_t *hba; 6986 emlxs_port_t *port; 6987 emlxs_config_t *cfg; 6988 char *prop_str; 6989 int ddiinst; 6990 int32_t emlxinst; 6991 int status; 6992 uint32_t rval; 6993 uint32_t init_flag = 0; 6994 char local_pm_components[32]; 6995 uint32_t i; 6996 6997 ddiinst = ddi_get_instance(dip); 6998 emlxinst = emlxs_add_instance(ddiinst); 6999 7000 if (emlxinst >= MAX_FC_BRDS) { 7001 cmn_err(CE_WARN, 7002 "?%s: fca_hba_attach failed. Too many driver ddiinsts. " 7003 "inst=%x", DRIVER_NAME, ddiinst); 7004 return (DDI_FAILURE); 7005 } 7006 7007 if (emlxs_device.hba[emlxinst] == (emlxs_hba_t *)-1) { 7008 return (DDI_FAILURE); 7009 } 7010 7011 if (emlxs_device.hba[emlxinst]) { 7012 return (DDI_SUCCESS); 7013 } 7014 7015 /* An adapter can accidentally be plugged into a slave-only PCI slot */ 7016 if (ddi_slaveonly(dip) == DDI_SUCCESS) { 7017 cmn_err(CE_WARN, 7018 "?%s%d: fca_hba_attach failed. Device in slave-only slot.", 7019 DRIVER_NAME, ddiinst); 7020 return (DDI_FAILURE); 7021 } 7022 7023 /* Allocate emlxs_dev_ctl structure. */ 7024 if (ddi_soft_state_zalloc(emlxs_soft_state, ddiinst) != DDI_SUCCESS) { 7025 cmn_err(CE_WARN, 7026 "?%s%d: fca_hba_attach failed. Unable to allocate soft " 7027 "state.", DRIVER_NAME, ddiinst); 7028 return (DDI_FAILURE); 7029 } 7030 init_flag |= ATTACH_SOFT_STATE; 7031 7032 if ((hba = (emlxs_hba_t *)ddi_get_soft_state(emlxs_soft_state, 7033 ddiinst)) == NULL) { 7034 cmn_err(CE_WARN, 7035 "?%s%d: fca_hba_attach failed. Unable to get soft state.", 7036 DRIVER_NAME, ddiinst); 7037 goto failed; 7038 } 7039 bzero((char *)hba, sizeof (emlxs_hba_t)); 7040 7041 emlxs_device.hba[emlxinst] = hba; 7042 emlxs_device.log[emlxinst] = &hba->log; 7043 7044 #ifdef DUMP_SUPPORT 7045 emlxs_device.dump_txtfile[emlxinst] = &hba->dump_txtfile; 7046 emlxs_device.dump_dmpfile[emlxinst] = &hba->dump_dmpfile; 7047 emlxs_device.dump_ceefile[emlxinst] = &hba->dump_ceefile; 7048 #endif /* DUMP_SUPPORT */ 7049 7050 hba->dip = dip; 7051 hba->emlxinst = emlxinst; 7052 hba->ddiinst = ddiinst; 7053 7054 init_flag |= ATTACH_HBA; 7055 7056 /* Enable the physical port on this HBA */ 7057 port = &PPORT; 7058 port->hba = hba; 7059 port->vpi = 0; 7060 port->flag |= EMLXS_PORT_ENABLED; 7061 7062 /* Allocate a transport structure */ 7063 hba->fca_tran = 7064 (fc_fca_tran_t *)kmem_zalloc(sizeof (fc_fca_tran_t), KM_NOSLEEP); 7065 if (hba->fca_tran == NULL) { 7066 cmn_err(CE_WARN, 7067 "?%s%d: fca_hba_attach failed. Unable to allocate fca_tran " 7068 "memory.", DRIVER_NAME, ddiinst); 7069 goto failed; 7070 } 7071 bcopy((caddr_t)&emlxs_fca_tran, (caddr_t)hba->fca_tran, 7072 sizeof (fc_fca_tran_t)); 7073 7074 /* 7075 * Copy the global ddi_dma_attr to the local hba fields 7076 */ 7077 bcopy((caddr_t)&emlxs_dma_attr, (caddr_t)&hba->dma_attr, 7078 sizeof (ddi_dma_attr_t)); 7079 bcopy((caddr_t)&emlxs_dma_attr_ro, (caddr_t)&hba->dma_attr_ro, 7080 sizeof (ddi_dma_attr_t)); 7081 bcopy((caddr_t)&emlxs_dma_attr_1sg, (caddr_t)&hba->dma_attr_1sg, 7082 sizeof (ddi_dma_attr_t)); 7083 bcopy((caddr_t)&emlxs_dma_attr_fcip_rsp, 7084 (caddr_t)&hba->dma_attr_fcip_rsp, sizeof (ddi_dma_attr_t)); 7085 7086 /* Reset the fca_tran dma_attr fields to the per-hba copies */ 7087 hba->fca_tran->fca_dma_attr = &hba->dma_attr; 7088 hba->fca_tran->fca_dma_fcp_cmd_attr = &hba->dma_attr_1sg; 7089 hba->fca_tran->fca_dma_fcp_rsp_attr = &hba->dma_attr_1sg; 7090 hba->fca_tran->fca_dma_fcp_data_attr = &hba->dma_attr_ro; 7091 hba->fca_tran->fca_dma_fcip_cmd_attr = &hba->dma_attr_1sg; 7092 hba->fca_tran->fca_dma_fcip_rsp_attr = &hba->dma_attr_fcip_rsp; 7093 hba->fca_tran->fca_dma_fcsm_cmd_attr = &hba->dma_attr_1sg; 7094 hba->fca_tran->fca_dma_fcsm_rsp_attr = &hba->dma_attr; 7095 7096 /* Set the transport structure pointer in our dip */ 7097 /* SFS may panic if we are in target only mode */ 7098 /* We will update the transport structure later */ 7099 (void) ddi_set_driver_private(dip, (caddr_t)&emlxs_fca_tran); 7100 init_flag |= ATTACH_FCA_TRAN; 7101 7102 /* Perform driver integrity check */ 7103 rval = emlxs_integrity_check(hba); 7104 if (rval) { 7105 cmn_err(CE_WARN, 7106 "?%s%d: fca_hba_attach failed. Driver integrity check " 7107 "failed. %d error(s) found.", DRIVER_NAME, ddiinst, rval); 7108 goto failed; 7109 } 7110 7111 cfg = &CFG; 7112 7113 bcopy((uint8_t *)&emlxs_cfg, (uint8_t *)cfg, sizeof (emlxs_cfg)); 7114 #ifdef MSI_SUPPORT 7115 if ((void *)&ddi_intr_get_supported_types != NULL) { 7116 hba->intr_flags |= EMLXS_MSI_ENABLED; 7117 } 7118 #endif /* MSI_SUPPORT */ 7119 7120 7121 /* Create the msg log file */ 7122 if (emlxs_msg_log_create(hba) == 0) { 7123 cmn_err(CE_WARN, 7124 "?%s%d: fca_hba_attach failed. Unable to create message " 7125 "log", DRIVER_NAME, ddiinst); 7126 goto failed; 7127 7128 } 7129 init_flag |= ATTACH_LOG; 7130 7131 /* We can begin to use EMLXS_MSGF from this point on */ 7132 7133 /* 7134 * Find the I/O bus type If it is not a SBUS card, 7135 * then it is a PCI card. Default is PCI_FC (0). 7136 */ 7137 prop_str = NULL; 7138 status = ddi_prop_lookup_string(DDI_DEV_T_ANY, 7139 (dev_info_t *)dip, 0, "name", (char **)&prop_str); 7140 7141 if (status == DDI_PROP_SUCCESS) { 7142 if (strncmp(prop_str, "lpfs", 4) == 0) { 7143 hba->bus_type = SBUS_FC; 7144 } 7145 7146 (void) ddi_prop_free((void *)prop_str); 7147 } 7148 7149 /* 7150 * Copy DDS from the config method and update configuration parameters 7151 */ 7152 (void) emlxs_get_props(hba); 7153 7154 #ifdef FMA_SUPPORT 7155 hba->fm_caps = cfg[CFG_FM_CAPS].current; 7156 7157 emlxs_fm_init(hba); 7158 7159 init_flag |= ATTACH_FM; 7160 #endif /* FMA_SUPPORT */ 7161 7162 if (emlxs_map_bus(hba)) { 7163 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7164 "Unable to map memory"); 7165 goto failed; 7166 7167 } 7168 init_flag |= ATTACH_MAP_BUS; 7169 7170 /* Attempt to identify the adapter */ 7171 rval = emlxs_init_adapter_info(hba); 7172 7173 if (rval == 0) { 7174 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7175 "Unable to get adapter info. Id:%d Device id:0x%x " 7176 "Model:%s", hba->model_info.id, 7177 hba->model_info.device_id, hba->model_info.model); 7178 goto failed; 7179 } 7180 #define FILTER_ORACLE_BRANDED 7181 #ifdef FILTER_ORACLE_BRANDED 7182 7183 /* Oracle branded adapters are not supported in this driver */ 7184 if (hba->model_info.flags & EMLXS_ORACLE_BRANDED) { 7185 hba->model_info.flags |= EMLXS_NOT_SUPPORTED; 7186 } 7187 #endif /* FILTER_ORACLE_BRANDED */ 7188 7189 /* Check if adapter is not supported */ 7190 if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { 7191 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7192 "Unsupported adapter found. Id:%d Device id:0x%x " 7193 "SSDID:0x%x Model:%s", hba->model_info.id, 7194 hba->model_info.device_id, 7195 hba->model_info.ssdid, hba->model_info.model); 7196 goto failed; 7197 } 7198 7199 if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 7200 hba->sli.sli4.mem_sgl_size = MEM_SGL_SIZE; 7201 7202 #ifdef EMLXS_I386 7203 /* 7204 * TigerShark has 64K limit for SG element size 7205 * Do this for x86 alone. For SPARC, the driver 7206 * breaks up the single SGE later on. 7207 */ 7208 hba->dma_attr_ro.dma_attr_count_max = 0xffff; 7209 7210 i = cfg[CFG_MAX_XFER_SIZE].current; 7211 /* Update SGL size based on max_xfer_size */ 7212 if (i > 516096) { 7213 /* 516096 = (((2048 / 16) - 2) * 4096) */ 7214 hba->sli.sli4.mem_sgl_size = 4096; 7215 } else if (i > 253952) { 7216 /* 253952 = (((1024 / 16) - 2) * 4096) */ 7217 hba->sli.sli4.mem_sgl_size = 2048; 7218 } else { 7219 hba->sli.sli4.mem_sgl_size = 1024; 7220 } 7221 #endif /* EMLXS_I386 */ 7222 7223 i = SGL_TO_SGLLEN(hba->sli.sli4.mem_sgl_size); 7224 } else { 7225 hba->sli.sli3.mem_bpl_size = MEM_BPL_SIZE; 7226 7227 #ifdef EMLXS_I386 7228 i = cfg[CFG_MAX_XFER_SIZE].current; 7229 /* Update BPL size based on max_xfer_size */ 7230 if (i > 688128) { 7231 /* 688128 = (((2048 / 12) - 2) * 4096) */ 7232 hba->sli.sli3.mem_bpl_size = 4096; 7233 } else if (i > 339968) { 7234 /* 339968 = (((1024 / 12) - 2) * 4096) */ 7235 hba->sli.sli3.mem_bpl_size = 2048; 7236 } else { 7237 hba->sli.sli3.mem_bpl_size = 1024; 7238 } 7239 #endif /* EMLXS_I386 */ 7240 7241 i = BPL_TO_SGLLEN(hba->sli.sli3.mem_bpl_size); 7242 } 7243 7244 /* Update dma_attr_sgllen based on true SGL length */ 7245 hba->dma_attr.dma_attr_sgllen = i; 7246 hba->dma_attr_ro.dma_attr_sgllen = i; 7247 hba->dma_attr_fcip_rsp.dma_attr_sgllen = i; 7248 7249 if (EMLXS_SLI_MAP_HDW(hba)) { 7250 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7251 "Unable to map memory"); 7252 goto failed; 7253 7254 } 7255 init_flag |= ATTACH_MAP_SLI; 7256 7257 /* Initialize the interrupts. But don't add them yet */ 7258 status = EMLXS_INTR_INIT(hba, 0); 7259 if (status != DDI_SUCCESS) { 7260 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7261 "Unable to initalize interrupt(s)."); 7262 goto failed; 7263 7264 } 7265 init_flag |= ATTACH_INTR_INIT; 7266 7267 /* Initialize LOCKs */ 7268 emlxs_msg_lock_reinit(hba); 7269 emlxs_lock_init(hba); 7270 init_flag |= ATTACH_LOCK; 7271 7272 /* Create the event queue */ 7273 if (emlxs_event_queue_create(hba) == 0) { 7274 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7275 "Unable to create event queue"); 7276 7277 goto failed; 7278 7279 } 7280 init_flag |= ATTACH_EVENTS; 7281 7282 /* Initialize the power management */ 7283 mutex_enter(&EMLXS_PM_LOCK); 7284 hba->pm_state = EMLXS_PM_IN_ATTACH; 7285 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 7286 hba->pm_busy = 0; 7287 #ifdef IDLE_TIMER 7288 hba->pm_active = 1; 7289 hba->pm_idle_timer = 0; 7290 #endif /* IDLE_TIMER */ 7291 mutex_exit(&EMLXS_PM_LOCK); 7292 7293 /* Set the pm component name */ 7294 (void) snprintf(local_pm_components, sizeof (local_pm_components), 7295 "NAME=%s%d", DRIVER_NAME, ddiinst); 7296 emlxs_pm_components[0] = local_pm_components; 7297 7298 /* Check if power management support is enabled */ 7299 if (cfg[CFG_PM_SUPPORT].current) { 7300 if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip, 7301 "pm-components", emlxs_pm_components, 7302 sizeof (emlxs_pm_components) / 7303 sizeof (emlxs_pm_components[0])) != 7304 DDI_PROP_SUCCESS) { 7305 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7306 "Unable to create pm components."); 7307 goto failed; 7308 } 7309 } 7310 7311 /* Needed for suspend and resume support */ 7312 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "pm-hardware-state", 7313 "needs-suspend-resume"); 7314 init_flag |= ATTACH_PROP; 7315 7316 emlxs_thread_spawn_create(hba); 7317 init_flag |= ATTACH_SPAWN; 7318 7319 emlxs_thread_create(hba, &hba->iodone_thread); 7320 7321 init_flag |= ATTACH_THREAD; 7322 7323 retry: 7324 /* Setup initiator / target ports */ 7325 emlxs_mode_init(hba); 7326 7327 /* If driver did not attach to either stack, */ 7328 /* then driver attach fails */ 7329 if (port->mode == MODE_NONE) { 7330 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7331 "Driver interfaces not enabled."); 7332 goto failed; 7333 } 7334 7335 /* 7336 * Initialize HBA 7337 */ 7338 7339 /* Set initial state */ 7340 mutex_enter(&EMLXS_PORT_LOCK); 7341 hba->flag |= FC_OFFLINE_MODE; 7342 hba->flag &= ~(FC_ONLINE_MODE | FC_ONLINING_MODE | FC_OFFLINING_MODE); 7343 mutex_exit(&EMLXS_PORT_LOCK); 7344 7345 if (status = emlxs_online(hba)) { 7346 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7347 "Unable to initialize adapter."); 7348 7349 if (status == EAGAIN) { 7350 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7351 "Retrying adapter initialization ..."); 7352 goto retry; 7353 } 7354 goto failed; 7355 } 7356 init_flag |= ATTACH_ONLINE; 7357 7358 /* This is to ensure that the model property is properly set */ 7359 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model", 7360 hba->model_info.model); 7361 7362 /* Create the device node. */ 7363 if (ddi_create_minor_node(dip, "devctl", S_IFCHR, ddiinst, NULL, 0) == 7364 DDI_FAILURE) { 7365 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 7366 "Unable to create device node."); 7367 goto failed; 7368 } 7369 init_flag |= ATTACH_NODE; 7370 7371 /* Attach initiator now */ 7372 /* This must come after emlxs_online() */ 7373 emlxs_fca_attach(hba); 7374 init_flag |= ATTACH_FCA; 7375 7376 /* Initialize kstat information */ 7377 hba->kstat = kstat_create(DRIVER_NAME, 7378 ddiinst, "statistics", "controller", 7379 KSTAT_TYPE_RAW, sizeof (emlxs_stats_t), 7380 KSTAT_FLAG_VIRTUAL); 7381 7382 if (hba->kstat == NULL) { 7383 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 7384 "kstat_create failed."); 7385 } else { 7386 hba->kstat->ks_data = (void *)&hba->stats; 7387 kstat_install(hba->kstat); 7388 init_flag |= ATTACH_KSTAT; 7389 } 7390 7391 #if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4) 7392 /* Setup virtual port properties */ 7393 emlxs_read_vport_prop(hba); 7394 #endif /* EMLXS_MODREV3 || EMLXS_MODREV4 */ 7395 7396 7397 #ifdef DHCHAP_SUPPORT 7398 emlxs_dhc_attach(hba); 7399 init_flag |= ATTACH_DHCHAP; 7400 #endif /* DHCHAP_SUPPORT */ 7401 7402 /* Display the driver banner now */ 7403 emlxs_drv_banner(hba); 7404 7405 /* Raise the power level */ 7406 7407 /* 7408 * This will not execute emlxs_hba_resume because 7409 * EMLXS_PM_IN_ATTACH is set 7410 */ 7411 if (emlxs_pm_raise_power(dip) != DDI_SUCCESS) { 7412 /* Set power up anyway. This should not happen! */ 7413 mutex_enter(&EMLXS_PM_LOCK); 7414 hba->pm_level = EMLXS_PM_ADAPTER_UP; 7415 hba->pm_state &= ~EMLXS_PM_IN_ATTACH; 7416 mutex_exit(&EMLXS_PM_LOCK); 7417 } else { 7418 mutex_enter(&EMLXS_PM_LOCK); 7419 hba->pm_state &= ~EMLXS_PM_IN_ATTACH; 7420 mutex_exit(&EMLXS_PM_LOCK); 7421 } 7422 7423 #ifdef SFCT_SUPPORT 7424 if (port->flag & EMLXS_TGT_ENABLED) { 7425 /* Do this last */ 7426 emlxs_fct_attach(hba); 7427 init_flag |= ATTACH_FCT; 7428 } 7429 #endif /* SFCT_SUPPORT */ 7430 7431 return (DDI_SUCCESS); 7432 7433 failed: 7434 7435 emlxs_driver_remove(dip, init_flag, 1); 7436 7437 return (DDI_FAILURE); 7438 7439 } /* emlxs_hba_attach() */ 7440 7441 7442 static int 7443 emlxs_hba_detach(dev_info_t *dip) 7444 { 7445 emlxs_hba_t *hba; 7446 emlxs_port_t *port; 7447 int ddiinst; 7448 int count; 7449 uint32_t init_flag = (uint32_t)-1; 7450 7451 ddiinst = ddi_get_instance(dip); 7452 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 7453 port = &PPORT; 7454 7455 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, NULL); 7456 7457 mutex_enter(&EMLXS_PM_LOCK); 7458 hba->pm_state |= EMLXS_PM_IN_DETACH; 7459 mutex_exit(&EMLXS_PM_LOCK); 7460 7461 /* Lower the power level */ 7462 /* 7463 * This will not suspend the driver since the 7464 * EMLXS_PM_IN_DETACH has been set 7465 */ 7466 if (emlxs_pm_lower_power(dip) != DDI_SUCCESS) { 7467 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 7468 "Unable to lower power."); 7469 7470 mutex_enter(&EMLXS_PM_LOCK); 7471 hba->pm_state &= ~EMLXS_PM_IN_DETACH; 7472 mutex_exit(&EMLXS_PM_LOCK); 7473 7474 return (DDI_FAILURE); 7475 } 7476 7477 /* Take the adapter offline first, if not already */ 7478 if (emlxs_offline(hba, 1) != 0) { 7479 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 7480 "Unable to take adapter offline."); 7481 7482 mutex_enter(&EMLXS_PM_LOCK); 7483 hba->pm_state &= ~EMLXS_PM_IN_DETACH; 7484 mutex_exit(&EMLXS_PM_LOCK); 7485 7486 (void) emlxs_pm_raise_power(dip); 7487 7488 return (DDI_FAILURE); 7489 } 7490 /* Check ub buffer pools */ 7491 if (port->ub_pool) { 7492 mutex_enter(&EMLXS_UB_LOCK); 7493 7494 /* Wait up to 10 seconds for all ub pools to be freed */ 7495 count = 10 * 2; 7496 while (port->ub_pool && count) { 7497 mutex_exit(&EMLXS_UB_LOCK); 7498 delay(drv_usectohz(500000)); /* half second wait */ 7499 count--; 7500 mutex_enter(&EMLXS_UB_LOCK); 7501 } 7502 7503 if (port->ub_pool) { 7504 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 7505 "fca_unbind_port: Unsolicited buffers still " 7506 "active. port=%p. Destroying...", port); 7507 7508 /* Destroy all pools */ 7509 while (port->ub_pool) { 7510 emlxs_ub_destroy(port, port->ub_pool); 7511 } 7512 } 7513 7514 mutex_exit(&EMLXS_UB_LOCK); 7515 } 7516 init_flag &= ~ATTACH_ONLINE; 7517 7518 /* Remove the driver instance */ 7519 emlxs_driver_remove(dip, init_flag, 0); 7520 7521 return (DDI_SUCCESS); 7522 7523 } /* emlxs_hba_detach() */ 7524 7525 7526 extern int 7527 emlxs_map_bus(emlxs_hba_t *hba) 7528 { 7529 emlxs_port_t *port = &PPORT; 7530 dev_info_t *dip; 7531 ddi_device_acc_attr_t dev_attr; 7532 int status; 7533 7534 dip = (dev_info_t *)hba->dip; 7535 dev_attr = emlxs_dev_acc_attr; 7536 7537 if (hba->bus_type == SBUS_FC) { 7538 if (hba->pci_acc_handle == 0) { 7539 status = ddi_regs_map_setup(dip, 7540 SBUS_DFLY_PCI_CFG_RINDEX, 7541 (caddr_t *)&hba->pci_addr, 7542 0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle); 7543 if (status != DDI_SUCCESS) { 7544 EMLXS_MSGF(EMLXS_CONTEXT, 7545 &emlxs_attach_failed_msg, 7546 "(SBUS) ddi_regs_map_setup PCI failed. " 7547 "status=%x", status); 7548 goto failed; 7549 } 7550 } 7551 7552 if (hba->sbus_pci_handle == 0) { 7553 status = ddi_regs_map_setup(dip, 7554 SBUS_TITAN_PCI_CFG_RINDEX, 7555 (caddr_t *)&hba->sbus_pci_addr, 7556 0, 0, &dev_attr, &hba->sbus_pci_handle); 7557 if (status != DDI_SUCCESS) { 7558 EMLXS_MSGF(EMLXS_CONTEXT, 7559 &emlxs_attach_failed_msg, 7560 "(SBUS) ddi_regs_map_setup TITAN PCI " 7561 "failed. status=%x", status); 7562 goto failed; 7563 } 7564 } 7565 7566 } else { /* ****** PCI ****** */ 7567 7568 if (hba->pci_acc_handle == 0) { 7569 status = ddi_regs_map_setup(dip, 7570 PCI_CFG_RINDEX, 7571 (caddr_t *)&hba->pci_addr, 7572 0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle); 7573 if (status != DDI_SUCCESS) { 7574 EMLXS_MSGF(EMLXS_CONTEXT, 7575 &emlxs_attach_failed_msg, 7576 "(PCI) ddi_regs_map_setup PCI failed. " 7577 "status=%x", status); 7578 goto failed; 7579 } 7580 } 7581 #ifdef EMLXS_I386 7582 /* Setting up PCI configure space */ 7583 (void) ddi_put16(hba->pci_acc_handle, 7584 (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 7585 CMD_CFG_VALUE | CMD_IO_ENBL); 7586 7587 #ifdef FMA_SUPPORT 7588 if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 7589 != DDI_FM_OK) { 7590 EMLXS_MSGF(EMLXS_CONTEXT, 7591 &emlxs_invalid_access_handle_msg, NULL); 7592 goto failed; 7593 } 7594 #endif /* FMA_SUPPORT */ 7595 7596 #endif /* EMLXS_I386 */ 7597 7598 } 7599 return (0); 7600 7601 failed: 7602 7603 emlxs_unmap_bus(hba); 7604 return (ENOMEM); 7605 7606 } /* emlxs_map_bus() */ 7607 7608 7609 extern void 7610 emlxs_unmap_bus(emlxs_hba_t *hba) 7611 { 7612 if (hba->pci_acc_handle) { 7613 (void) ddi_regs_map_free(&hba->pci_acc_handle); 7614 hba->pci_acc_handle = 0; 7615 } 7616 7617 if (hba->sbus_pci_handle) { 7618 (void) ddi_regs_map_free(&hba->sbus_pci_handle); 7619 hba->sbus_pci_handle = 0; 7620 } 7621 7622 return; 7623 7624 } /* emlxs_unmap_bus() */ 7625 7626 7627 static int 7628 emlxs_get_props(emlxs_hba_t *hba) 7629 { 7630 emlxs_config_t *cfg; 7631 uint32_t i; 7632 char string[256]; 7633 uint32_t new_value; 7634 7635 /* Initialize each parameter */ 7636 for (i = 0; i < NUM_CFG_PARAM; i++) { 7637 cfg = &hba->config[i]; 7638 7639 /* Ensure strings are terminated */ 7640 cfg->string[(EMLXS_CFG_STR_SIZE-1)] = 0; 7641 cfg->help[(EMLXS_CFG_HELP_SIZE-1)] = 0; 7642 7643 /* Set the current value to the default value */ 7644 new_value = cfg->def; 7645 7646 /* First check for the global setting */ 7647 new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, 7648 (void *)hba->dip, DDI_PROP_DONTPASS, 7649 cfg->string, new_value); 7650 7651 /* Now check for the per adapter ddiinst setting */ 7652 (void) snprintf(string, sizeof (string), "%s%d-%s", DRIVER_NAME, 7653 hba->ddiinst, cfg->string); 7654 7655 new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, 7656 (void *)hba->dip, DDI_PROP_DONTPASS, string, new_value); 7657 7658 /* Now check the parameter */ 7659 cfg->current = emlxs_check_parm(hba, i, new_value); 7660 } 7661 7662 return (0); 7663 7664 } /* emlxs_get_props() */ 7665 7666 7667 extern uint32_t 7668 emlxs_check_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value) 7669 { 7670 emlxs_port_t *port = &PPORT; 7671 uint32_t i; 7672 emlxs_config_t *cfg; 7673 emlxs_vpd_t *vpd = &VPD; 7674 7675 if (index >= NUM_CFG_PARAM) { 7676 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 7677 "check_parm failed. Invalid index = %d", index); 7678 7679 return (new_value); 7680 } 7681 7682 cfg = &hba->config[index]; 7683 7684 if (new_value > cfg->hi) { 7685 new_value = cfg->def; 7686 } else if (new_value < cfg->low) { 7687 new_value = cfg->def; 7688 } 7689 7690 /* Perform additional checks */ 7691 switch (index) { 7692 #ifdef SFCT_SUPPORT 7693 case CFG_NPIV_ENABLE: 7694 if (hba->config[CFG_TARGET_MODE].current && 7695 hba->config[CFG_DTM_ENABLE].current == 0) { 7696 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 7697 "enable-npiv: Not supported in pure target mode. " 7698 "Disabling."); 7699 7700 new_value = 0; 7701 } 7702 break; 7703 #endif /* SFCT_SUPPORT */ 7704 7705 7706 case CFG_NUM_NODES: 7707 switch (new_value) { 7708 case 1: 7709 case 2: 7710 /* Must have at least 3 if not 0 */ 7711 return (3); 7712 7713 default: 7714 break; 7715 } 7716 break; 7717 7718 case CFG_FW_CHECK: 7719 /* The 0x2 bit implies the 0x1 bit will also be set */ 7720 if (new_value & 0x2) { 7721 new_value |= 0x1; 7722 } 7723 7724 /* The 0x4 bit should not be set if 0x1 or 0x2 is not set */ 7725 if (!(new_value & 0x3) && (new_value & 0x4)) { 7726 new_value &= ~0x4; 7727 } 7728 break; 7729 7730 case CFG_LINK_SPEED: 7731 if ((new_value > 8) && 7732 (hba->config[CFG_TOPOLOGY].current == 4)) { 7733 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 7734 "link-speed: %dGb not supported in loop topology. " 7735 "Switching to auto detect.", 7736 new_value); 7737 7738 new_value = 0; 7739 break; 7740 } 7741 7742 if (vpd->link_speed) { 7743 switch (new_value) { 7744 case 0: 7745 break; 7746 7747 case 1: 7748 if (!(vpd->link_speed & LMT_1GB_CAPABLE)) { 7749 new_value = 0; 7750 7751 EMLXS_MSGF(EMLXS_CONTEXT, 7752 &emlxs_init_msg, 7753 "link-speed: 1Gb not supported " 7754 "by adapter. Switching to auto " 7755 "detect."); 7756 } 7757 break; 7758 7759 case 2: 7760 if (!(vpd->link_speed & LMT_2GB_CAPABLE)) { 7761 new_value = 0; 7762 7763 EMLXS_MSGF(EMLXS_CONTEXT, 7764 &emlxs_init_msg, 7765 "link-speed: 2Gb not supported " 7766 "by adapter. Switching to auto " 7767 "detect."); 7768 } 7769 break; 7770 7771 case 4: 7772 if (!(vpd->link_speed & LMT_4GB_CAPABLE)) { 7773 new_value = 0; 7774 7775 EMLXS_MSGF(EMLXS_CONTEXT, 7776 &emlxs_init_msg, 7777 "link-speed: 4Gb not supported " 7778 "by adapter. Switching to auto " 7779 "detect."); 7780 } 7781 break; 7782 7783 case 8: 7784 if (!(vpd->link_speed & LMT_8GB_CAPABLE)) { 7785 new_value = 0; 7786 7787 EMLXS_MSGF(EMLXS_CONTEXT, 7788 &emlxs_init_msg, 7789 "link-speed: 8Gb not supported " 7790 "by adapter. Switching to auto " 7791 "detect."); 7792 } 7793 break; 7794 7795 case 16: 7796 if (!(vpd->link_speed & LMT_16GB_CAPABLE)) { 7797 new_value = 0; 7798 7799 EMLXS_MSGF(EMLXS_CONTEXT, 7800 &emlxs_init_msg, 7801 "link-speed: 16Gb not supported " 7802 "by adapter. Switching to auto " 7803 "detect."); 7804 } 7805 break; 7806 7807 default: 7808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 7809 "link-speed: Invalid value=%d provided. " 7810 "Switching to auto detect.", 7811 new_value); 7812 7813 new_value = 0; 7814 } 7815 } else { /* Perform basic validity check */ 7816 7817 /* Perform additional check on link speed */ 7818 switch (new_value) { 7819 case 0: 7820 case 1: 7821 case 2: 7822 case 4: 7823 case 8: 7824 case 16: 7825 /* link-speed is a valid choice */ 7826 break; 7827 7828 default: 7829 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 7830 "link-speed: Invalid value=%d provided. " 7831 "Switching to auto detect.", 7832 new_value); 7833 7834 new_value = 0; 7835 } 7836 } 7837 break; 7838 7839 case CFG_TOPOLOGY: 7840 if ((new_value == 4) && 7841 (hba->config[CFG_LINK_SPEED].current > 8)) { 7842 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 7843 "topology: Loop topology not supported " 7844 "with link speeds greater than 8Gb. " 7845 "Switching to auto detect."); 7846 7847 new_value = 0; 7848 break; 7849 } 7850 7851 /* Perform additional check on topology */ 7852 switch (new_value) { 7853 case 0: 7854 case 2: 7855 case 4: 7856 case 6: 7857 /* topology is a valid choice */ 7858 break; 7859 7860 default: 7861 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 7862 "topology: Invalid value=%d provided. " 7863 "Switching to auto detect.", 7864 new_value); 7865 7866 new_value = 0; 7867 break; 7868 } 7869 break; 7870 7871 #ifdef DHCHAP_SUPPORT 7872 case CFG_AUTH_TYPE: 7873 { 7874 uint32_t shift; 7875 uint32_t mask; 7876 7877 /* Perform additional check on auth type */ 7878 shift = 12; 7879 mask = 0xF000; 7880 for (i = 0; i < 4; i++) { 7881 if (((new_value & mask) >> shift) > DFC_AUTH_TYPE_MAX) { 7882 return (cfg->def); 7883 } 7884 7885 shift -= 4; 7886 mask >>= 4; 7887 } 7888 break; 7889 } 7890 7891 case CFG_AUTH_HASH: 7892 { 7893 uint32_t shift; 7894 uint32_t mask; 7895 7896 /* Perform additional check on auth hash */ 7897 shift = 12; 7898 mask = 0xF000; 7899 for (i = 0; i < 4; i++) { 7900 if (((new_value & mask) >> shift) > DFC_AUTH_HASH_MAX) { 7901 return (cfg->def); 7902 } 7903 7904 shift -= 4; 7905 mask >>= 4; 7906 } 7907 break; 7908 } 7909 7910 case CFG_AUTH_GROUP: 7911 { 7912 uint32_t shift; 7913 uint32_t mask; 7914 7915 /* Perform additional check on auth group */ 7916 shift = 28; 7917 mask = 0xF0000000; 7918 for (i = 0; i < 8; i++) { 7919 if (((new_value & mask) >> shift) > 7920 DFC_AUTH_GROUP_MAX) { 7921 return (cfg->def); 7922 } 7923 7924 shift -= 4; 7925 mask >>= 4; 7926 } 7927 break; 7928 } 7929 7930 case CFG_AUTH_INTERVAL: 7931 if (new_value < 10) { 7932 return (10); 7933 } 7934 break; 7935 7936 7937 #endif /* DHCHAP_SUPPORT */ 7938 7939 } /* switch */ 7940 7941 return (new_value); 7942 7943 } /* emlxs_check_parm() */ 7944 7945 7946 extern uint32_t 7947 emlxs_set_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value) 7948 { 7949 emlxs_port_t *port = &PPORT; 7950 emlxs_port_t *vport; 7951 uint32_t vpi; 7952 emlxs_config_t *cfg; 7953 uint32_t old_value; 7954 7955 if (index >= NUM_CFG_PARAM) { 7956 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 7957 "set_parm failed. Invalid index = %d", index); 7958 7959 return ((uint32_t)FC_FAILURE); 7960 } 7961 7962 cfg = &hba->config[index]; 7963 7964 if (!(cfg->flags & PARM_DYNAMIC)) { 7965 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 7966 "set_parm failed. %s is not dynamic.", cfg->string); 7967 7968 return ((uint32_t)FC_FAILURE); 7969 } 7970 7971 /* Check new value */ 7972 old_value = new_value; 7973 new_value = emlxs_check_parm(hba, index, new_value); 7974 7975 if (old_value != new_value) { 7976 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 7977 "set_parm: %s invalid. 0x%x --> 0x%x", 7978 cfg->string, old_value, new_value); 7979 } 7980 7981 /* Return now if no actual change */ 7982 if (new_value == cfg->current) { 7983 return (FC_SUCCESS); 7984 } 7985 7986 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 7987 "set_parm: %s changing. 0x%x --> 0x%x", 7988 cfg->string, cfg->current, new_value); 7989 7990 old_value = cfg->current; 7991 cfg->current = new_value; 7992 7993 /* React to change if needed */ 7994 switch (index) { 7995 7996 case CFG_PCI_MAX_READ: 7997 /* Update MXR */ 7998 emlxs_pcix_mxr_update(hba, 1); 7999 break; 8000 8001 #ifdef SFCT_SUPPORT 8002 case CFG_TARGET_MODE: 8003 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 8004 break; 8005 #endif /* SFCT_SUPPORT */ 8006 8007 case CFG_SLI_MODE: 8008 /* Check SLI mode */ 8009 if ((hba->sli_mode == 3) && (new_value == 2)) { 8010 /* All vports must be disabled first */ 8011 for (vpi = 1; vpi < MAX_VPORTS; vpi++) { 8012 vport = &VPORT(vpi); 8013 8014 if (vport->flag & EMLXS_PORT_ENABLED) { 8015 /* Reset current value */ 8016 cfg->current = old_value; 8017 8018 EMLXS_MSGF(EMLXS_CONTEXT, 8019 &emlxs_sfs_debug_msg, 8020 "set_parm failed. %s: vpi=%d " 8021 "still enabled. Value restored to " 8022 "0x%x.", cfg->string, vpi, 8023 old_value); 8024 8025 return (2); 8026 } 8027 } 8028 } 8029 8030 if ((hba->sli_mode >= 4) && (new_value < 4)) { 8031 /* 8032 * Not allow to set to SLI 2 or 3 if HBA supports SLI4 8033 */ 8034 cfg->current = old_value; 8035 return ((uint32_t)FC_FAILURE); 8036 } 8037 8038 break; 8039 8040 case CFG_NPIV_ENABLE: 8041 /* Check if NPIV is being disabled */ 8042 if ((old_value == 1) && (new_value == 0)) { 8043 /* All vports must be disabled first */ 8044 for (vpi = 1; vpi < MAX_VPORTS; vpi++) { 8045 vport = &VPORT(vpi); 8046 8047 if (vport->flag & EMLXS_PORT_ENABLED) { 8048 /* Reset current value */ 8049 cfg->current = old_value; 8050 8051 EMLXS_MSGF(EMLXS_CONTEXT, 8052 &emlxs_sfs_debug_msg, 8053 "set_parm failed. %s: vpi=%d " 8054 "still enabled. Value restored to " 8055 "0x%x.", cfg->string, vpi, 8056 old_value); 8057 8058 return (2); 8059 } 8060 } 8061 } 8062 8063 /* Trigger adapter reset */ 8064 /* (void) emlxs_reset(port, FC_FCA_RESET); */ 8065 8066 break; 8067 8068 8069 case CFG_VPORT_RESTRICTED: 8070 for (vpi = 0; vpi < MAX_VPORTS; vpi++) { 8071 vport = &VPORT(vpi); 8072 8073 if (!(vport->flag & EMLXS_PORT_CONFIG)) { 8074 continue; 8075 } 8076 8077 if (vport->options & EMLXS_OPT_RESTRICT_MASK) { 8078 continue; 8079 } 8080 8081 if (new_value) { 8082 vport->flag |= EMLXS_PORT_RESTRICTED; 8083 } else { 8084 vport->flag &= ~EMLXS_PORT_RESTRICTED; 8085 } 8086 } 8087 8088 break; 8089 8090 #ifdef DHCHAP_SUPPORT 8091 case CFG_AUTH_ENABLE: 8092 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 8093 break; 8094 8095 case CFG_AUTH_TMO: 8096 hba->auth_cfg.authentication_timeout = cfg->current; 8097 break; 8098 8099 case CFG_AUTH_MODE: 8100 hba->auth_cfg.authentication_mode = cfg->current; 8101 break; 8102 8103 case CFG_AUTH_BIDIR: 8104 hba->auth_cfg.bidirectional = cfg->current; 8105 break; 8106 8107 case CFG_AUTH_TYPE: 8108 hba->auth_cfg.authentication_type_priority[0] = 8109 (cfg->current & 0xF000) >> 12; 8110 hba->auth_cfg.authentication_type_priority[1] = 8111 (cfg->current & 0x0F00) >> 8; 8112 hba->auth_cfg.authentication_type_priority[2] = 8113 (cfg->current & 0x00F0) >> 4; 8114 hba->auth_cfg.authentication_type_priority[3] = 8115 (cfg->current & 0x000F); 8116 break; 8117 8118 case CFG_AUTH_HASH: 8119 hba->auth_cfg.hash_priority[0] = 8120 (cfg->current & 0xF000) >> 12; 8121 hba->auth_cfg.hash_priority[1] = (cfg->current & 0x0F00)>>8; 8122 hba->auth_cfg.hash_priority[2] = (cfg->current & 0x00F0)>>4; 8123 hba->auth_cfg.hash_priority[3] = (cfg->current & 0x000F); 8124 break; 8125 8126 case CFG_AUTH_GROUP: 8127 hba->auth_cfg.dh_group_priority[0] = 8128 (cfg->current & 0xF0000000) >> 28; 8129 hba->auth_cfg.dh_group_priority[1] = 8130 (cfg->current & 0x0F000000) >> 24; 8131 hba->auth_cfg.dh_group_priority[2] = 8132 (cfg->current & 0x00F00000) >> 20; 8133 hba->auth_cfg.dh_group_priority[3] = 8134 (cfg->current & 0x000F0000) >> 16; 8135 hba->auth_cfg.dh_group_priority[4] = 8136 (cfg->current & 0x0000F000) >> 12; 8137 hba->auth_cfg.dh_group_priority[5] = 8138 (cfg->current & 0x00000F00) >> 8; 8139 hba->auth_cfg.dh_group_priority[6] = 8140 (cfg->current & 0x000000F0) >> 4; 8141 hba->auth_cfg.dh_group_priority[7] = 8142 (cfg->current & 0x0000000F); 8143 break; 8144 8145 case CFG_AUTH_INTERVAL: 8146 hba->auth_cfg.reauthenticate_time_interval = cfg->current; 8147 break; 8148 #endif /* DHCHAP_SUPPORT */ 8149 8150 } 8151 8152 return (FC_SUCCESS); 8153 8154 } /* emlxs_set_parm() */ 8155 8156 8157 /* 8158 * emlxs_mem_alloc OS specific routine for memory allocation / mapping 8159 * 8160 * The buf_info->flags field describes the memory operation requested. 8161 * 8162 * FC_MBUF_PHYSONLY set requests a supplied virtual address be mapped for DMA 8163 * Virtual address is supplied in buf_info->virt 8164 * DMA mapping flag is in buf_info->align 8165 * (DMA_READ_ONLY, DMA_WRITE_ONLY, DMA_READ_WRITE) 8166 * The mapped physical address is returned buf_info->phys 8167 * 8168 * FC_MBUF_PHYSONLY cleared requests memory be allocated for driver use and 8169 * if FC_MBUF_DMA is set the memory is also mapped for DMA 8170 * The byte alignment of the memory request is supplied in buf_info->align 8171 * The byte size of the memory request is supplied in buf_info->size 8172 * The virtual address is returned buf_info->virt 8173 * The mapped physical address is returned buf_info->phys (for FC_MBUF_DMA) 8174 */ 8175 extern uint8_t * 8176 emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info) 8177 { 8178 emlxs_port_t *port = &PPORT; 8179 ddi_dma_attr_t dma_attr; 8180 ddi_device_acc_attr_t dev_attr; 8181 uint_t cookie_count; 8182 size_t dma_reallen; 8183 ddi_dma_cookie_t dma_cookie; 8184 uint_t dma_flag; 8185 int status; 8186 8187 dma_attr = hba->dma_attr_1sg; 8188 dev_attr = emlxs_data_acc_attr; 8189 8190 if (buf_info->flags & FC_MBUF_SNGLSG) { 8191 dma_attr.dma_attr_sgllen = 1; 8192 } 8193 8194 if (buf_info->flags & FC_MBUF_DMA32) { 8195 dma_attr.dma_attr_addr_hi = (uint64_t)0xffffffff; 8196 } 8197 8198 if (buf_info->flags & FC_MBUF_PHYSONLY) { 8199 8200 if (buf_info->virt == NULL) { 8201 goto done; 8202 } 8203 8204 /* 8205 * Allocate the DMA handle for this DMA object 8206 */ 8207 status = ddi_dma_alloc_handle((void *)hba->dip, 8208 &dma_attr, DDI_DMA_DONTWAIT, 8209 NULL, (ddi_dma_handle_t *)&buf_info->dma_handle); 8210 if (status != DDI_SUCCESS) { 8211 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 8212 "ddi_dma_alloc_handle failed: size=%x align=%x " 8213 "flags=%x", buf_info->size, buf_info->align, 8214 buf_info->flags); 8215 8216 buf_info->phys = 0; 8217 buf_info->dma_handle = 0; 8218 goto done; 8219 } 8220 8221 switch (buf_info->align) { 8222 case DMA_READ_WRITE: 8223 dma_flag = (DDI_DMA_RDWR | DDI_DMA_CONSISTENT); 8224 break; 8225 case DMA_READ_ONLY: 8226 dma_flag = (DDI_DMA_READ | DDI_DMA_CONSISTENT); 8227 break; 8228 case DMA_WRITE_ONLY: 8229 dma_flag = (DDI_DMA_WRITE | DDI_DMA_CONSISTENT); 8230 break; 8231 default: 8232 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 8233 "Invalid DMA flag"); 8234 (void) ddi_dma_free_handle( 8235 (ddi_dma_handle_t *)&buf_info->dma_handle); 8236 buf_info->phys = 0; 8237 buf_info->dma_handle = 0; 8238 return ((uint8_t *)buf_info->virt); 8239 } 8240 8241 /* Map this page of memory */ 8242 status = ddi_dma_addr_bind_handle( 8243 (ddi_dma_handle_t)buf_info->dma_handle, NULL, 8244 (caddr_t)buf_info->virt, (size_t)buf_info->size, 8245 dma_flag, DDI_DMA_DONTWAIT, NULL, &dma_cookie, 8246 &cookie_count); 8247 8248 if (status != DDI_DMA_MAPPED || (cookie_count > 1)) { 8249 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 8250 "ddi_dma_addr_bind_handle failed: status=%x " 8251 "count=%x flags=%x", status, cookie_count, 8252 buf_info->flags); 8253 8254 (void) ddi_dma_free_handle( 8255 (ddi_dma_handle_t *)&buf_info->dma_handle); 8256 buf_info->phys = 0; 8257 buf_info->dma_handle = 0; 8258 goto done; 8259 } 8260 8261 if (hba->bus_type == SBUS_FC) { 8262 8263 int32_t burstsizes_limit = 0xff; 8264 int32_t ret_burst; 8265 8266 ret_burst = ddi_dma_burstsizes( 8267 buf_info->dma_handle) & burstsizes_limit; 8268 if (ddi_dma_set_sbus64(buf_info->dma_handle, 8269 ret_burst) == DDI_FAILURE) { 8270 EMLXS_MSGF(EMLXS_CONTEXT, 8271 &emlxs_mem_alloc_failed_msg, 8272 "ddi_dma_set_sbus64 failed."); 8273 } 8274 } 8275 8276 /* Save Physical address */ 8277 buf_info->phys = dma_cookie.dmac_laddress; 8278 8279 /* 8280 * Just to be sure, let's add this 8281 */ 8282 EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle, 8283 (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV); 8284 8285 } else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) { 8286 8287 dma_attr.dma_attr_align = buf_info->align; 8288 8289 /* 8290 * Allocate the DMA handle for this DMA object 8291 */ 8292 status = ddi_dma_alloc_handle((void *)hba->dip, &dma_attr, 8293 DDI_DMA_DONTWAIT, NULL, 8294 (ddi_dma_handle_t *)&buf_info->dma_handle); 8295 if (status != DDI_SUCCESS) { 8296 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 8297 "ddi_dma_alloc_handle failed: size=%x align=%x " 8298 "flags=%x", buf_info->size, buf_info->align, 8299 buf_info->flags); 8300 8301 buf_info->virt = NULL; 8302 buf_info->phys = 0; 8303 buf_info->data_handle = 0; 8304 buf_info->dma_handle = 0; 8305 goto done; 8306 } 8307 8308 status = ddi_dma_mem_alloc( 8309 (ddi_dma_handle_t)buf_info->dma_handle, 8310 (size_t)buf_info->size, &dev_attr, DDI_DMA_CONSISTENT, 8311 DDI_DMA_DONTWAIT, NULL, (caddr_t *)&buf_info->virt, 8312 &dma_reallen, (ddi_acc_handle_t *)&buf_info->data_handle); 8313 8314 if ((status != DDI_SUCCESS) || (buf_info->size > dma_reallen)) { 8315 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 8316 "ddi_dma_mem_alloc failed: size=%x align=%x " 8317 "flags=%x", buf_info->size, buf_info->align, 8318 buf_info->flags); 8319 8320 (void) ddi_dma_free_handle( 8321 (ddi_dma_handle_t *)&buf_info->dma_handle); 8322 8323 buf_info->virt = NULL; 8324 buf_info->phys = 0; 8325 buf_info->data_handle = 0; 8326 buf_info->dma_handle = 0; 8327 goto done; 8328 } 8329 8330 /* Map this page of memory */ 8331 status = ddi_dma_addr_bind_handle( 8332 (ddi_dma_handle_t)buf_info->dma_handle, NULL, 8333 (caddr_t)buf_info->virt, (size_t)buf_info->size, 8334 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 8335 &dma_cookie, &cookie_count); 8336 8337 if (status != DDI_DMA_MAPPED || (cookie_count > 1)) { 8338 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 8339 "ddi_dma_addr_bind_handle failed: status=%x " 8340 "count=%d size=%x align=%x flags=%x", status, 8341 cookie_count, buf_info->size, buf_info->align, 8342 buf_info->flags); 8343 8344 (void) ddi_dma_mem_free( 8345 (ddi_acc_handle_t *)&buf_info->data_handle); 8346 (void) ddi_dma_free_handle( 8347 (ddi_dma_handle_t *)&buf_info->dma_handle); 8348 8349 buf_info->virt = NULL; 8350 buf_info->phys = 0; 8351 buf_info->dma_handle = 0; 8352 buf_info->data_handle = 0; 8353 goto done; 8354 } 8355 8356 if (hba->bus_type == SBUS_FC) { 8357 int32_t burstsizes_limit = 0xff; 8358 int32_t ret_burst; 8359 8360 ret_burst = 8361 ddi_dma_burstsizes(buf_info-> 8362 dma_handle) & burstsizes_limit; 8363 if (ddi_dma_set_sbus64(buf_info->dma_handle, 8364 ret_burst) == DDI_FAILURE) { 8365 EMLXS_MSGF(EMLXS_CONTEXT, 8366 &emlxs_mem_alloc_failed_msg, 8367 "ddi_dma_set_sbus64 failed."); 8368 } 8369 } 8370 8371 /* Save Physical address */ 8372 buf_info->phys = dma_cookie.dmac_laddress; 8373 8374 /* Just to be sure, let's add this */ 8375 EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle, 8376 (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV); 8377 8378 } else { /* allocate virtual memory */ 8379 8380 buf_info->virt = 8381 kmem_zalloc((size_t)buf_info->size, KM_NOSLEEP); 8382 buf_info->phys = 0; 8383 buf_info->data_handle = 0; 8384 buf_info->dma_handle = 0; 8385 8386 if (buf_info->virt == (uint32_t *)0) { 8387 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 8388 "size=%x flags=%x", buf_info->size, 8389 buf_info->flags); 8390 } 8391 8392 } 8393 8394 done: 8395 8396 return ((uint8_t *)buf_info->virt); 8397 8398 } /* emlxs_mem_alloc() */ 8399 8400 8401 8402 /* 8403 * emlxs_mem_free: 8404 * 8405 * OS specific routine for memory de-allocation / unmapping 8406 * 8407 * The buf_info->flags field describes the memory operation requested. 8408 * 8409 * FC_MBUF_PHYSONLY set requests a supplied virtual address be unmapped 8410 * for DMA, but not freed. The mapped physical address to be unmapped is in 8411 * buf_info->phys 8412 * 8413 * FC_MBUF_PHYSONLY cleared requests memory be freed and unmapped for DMA only 8414 * if FC_MBUF_DMA is set. The mapped physical address to be unmapped is in 8415 * buf_info->phys. The virtual address to be freed is in buf_info->virt 8416 */ 8417 /*ARGSUSED*/ 8418 extern void 8419 emlxs_mem_free(emlxs_hba_t *hba, MBUF_INFO *buf_info) 8420 { 8421 if (buf_info->flags & FC_MBUF_PHYSONLY) { 8422 8423 if (buf_info->dma_handle) { 8424 (void) ddi_dma_unbind_handle(buf_info->dma_handle); 8425 (void) ddi_dma_free_handle( 8426 (ddi_dma_handle_t *)&buf_info->dma_handle); 8427 buf_info->dma_handle = NULL; 8428 } 8429 8430 } else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) { 8431 8432 if (buf_info->dma_handle) { 8433 (void) ddi_dma_unbind_handle(buf_info->dma_handle); 8434 (void) ddi_dma_mem_free( 8435 (ddi_acc_handle_t *)&buf_info->data_handle); 8436 (void) ddi_dma_free_handle( 8437 (ddi_dma_handle_t *)&buf_info->dma_handle); 8438 buf_info->dma_handle = NULL; 8439 buf_info->data_handle = NULL; 8440 } 8441 8442 } else { /* allocate virtual memory */ 8443 8444 if (buf_info->virt) { 8445 kmem_free(buf_info->virt, (size_t)buf_info->size); 8446 buf_info->virt = NULL; 8447 } 8448 } 8449 8450 } /* emlxs_mem_free() */ 8451 8452 8453 static int 8454 emlxs_select_fcp_channel(emlxs_hba_t *hba, NODELIST *ndlp, int reset) 8455 { 8456 int channel; 8457 int msi_id; 8458 8459 8460 /* IO to FCP2 device or a device reset always use fcp channel */ 8461 if ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) || reset) { 8462 return (hba->channel_fcp); 8463 } 8464 8465 8466 msi_id = emlxs_select_msiid(hba); 8467 channel = emlxs_msiid_to_chan(hba, msi_id); 8468 8469 8470 8471 /* If channel is closed, then try fcp channel */ 8472 if (ndlp->nlp_flag[channel] & NLP_CLOSED) { 8473 channel = hba->channel_fcp; 8474 } 8475 return (channel); 8476 8477 } /* emlxs_select_fcp_channel() */ 8478 8479 8480 static int32_t 8481 emlxs_fast_target_reset(emlxs_port_t *port, emlxs_buf_t *sbp, NODELIST *ndlp) 8482 { 8483 emlxs_hba_t *hba = HBA; 8484 fc_packet_t *pkt; 8485 emlxs_config_t *cfg; 8486 MAILBOXQ *mbq; 8487 MAILBOX *mb; 8488 uint32_t rc; 8489 8490 /* 8491 * This routine provides a alternative target reset provessing 8492 * method. Instead of sending an actual target reset to the 8493 * NPort, we will first unreg the login to that NPort. This 8494 * will cause all the outstanding IOs the quickly complete with 8495 * a NO RPI local error. Next we will force the ULP to relogin 8496 * to the NPort by sending an RSCN (for that NPort) to the 8497 * upper layer. This method should result in a fast target 8498 * reset, as far as IOs completing; however, since an actual 8499 * target reset is not sent to the NPort, it is not 100% 8500 * compatable. Things like reservations will not be broken. 8501 * By default this option is DISABLED, and its only enabled thru 8502 * a hidden configuration parameter (fast-tgt-reset). 8503 */ 8504 rc = FC_TRAN_BUSY; 8505 pkt = PRIV2PKT(sbp); 8506 cfg = &CFG; 8507 8508 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) { 8509 /* issue the mbox cmd to the sli */ 8510 mb = (MAILBOX *) mbq->mbox; 8511 bzero((void *) mb, MAILBOX_CMD_BSIZE); 8512 mb->un.varUnregLogin.rpi = (uint16_t)ndlp->nlp_Rpi; 8513 #ifdef SLI3_SUPPORT 8514 mb->un.varUnregLogin.vpi = port->vpi; 8515 #endif /* SLI3_SUPPORT */ 8516 mb->mbxCommand = MBX_UNREG_LOGIN; 8517 mb->mbxOwner = OWN_HOST; 8518 8519 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8520 "Fast Target Reset: unreg rpi=%d tmr=%d", ndlp->nlp_Rpi, 8521 cfg[CFG_FAST_TGT_RESET_TMR].current); 8522 8523 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) 8524 == MBX_SUCCESS) { 8525 8526 ndlp->nlp_Rpi = 0; 8527 8528 mutex_enter(&sbp->mtx); 8529 sbp->node = (void *)ndlp; 8530 sbp->did = ndlp->nlp_DID; 8531 mutex_exit(&sbp->mtx); 8532 8533 if (pkt->pkt_rsplen) { 8534 bzero((uint8_t *)pkt->pkt_resp, 8535 pkt->pkt_rsplen); 8536 } 8537 if (cfg[CFG_FAST_TGT_RESET_TMR].current) { 8538 ndlp->nlp_force_rscn = hba->timer_tics + 8539 cfg[CFG_FAST_TGT_RESET_TMR].current; 8540 } 8541 8542 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 0); 8543 } 8544 8545 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 8546 rc = FC_SUCCESS; 8547 } 8548 return (rc); 8549 } /* emlxs_fast_target_reset() */ 8550 8551 static int32_t 8552 emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp, uint32_t *pkt_flags) 8553 { 8554 emlxs_hba_t *hba = HBA; 8555 fc_packet_t *pkt; 8556 emlxs_config_t *cfg; 8557 IOCBQ *iocbq; 8558 IOCB *iocb; 8559 CHANNEL *cp; 8560 NODELIST *ndlp; 8561 char *cmd; 8562 uint16_t lun; 8563 FCP_CMND *fcp_cmd; 8564 uint32_t did; 8565 uint32_t reset = 0; 8566 int channel; 8567 int32_t rval; 8568 8569 pkt = PRIV2PKT(sbp); 8570 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 8571 8572 /* Find target node object */ 8573 ndlp = emlxs_node_find_did(port, did, 1); 8574 8575 if (!ndlp || !ndlp->nlp_active) { 8576 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 8577 "Node not found. did=%x", did); 8578 8579 return (FC_BADPACKET); 8580 } 8581 8582 /* When the fcp channel is closed we stop accepting any FCP cmd */ 8583 if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) { 8584 return (FC_TRAN_BUSY); 8585 } 8586 8587 /* Snoop for target or lun reset first */ 8588 /* We always use FCP channel to send out target/lun reset fcp cmds */ 8589 /* interrupt affinity only applies to non tgt lun reset fcp cmd */ 8590 8591 cmd = (char *)pkt->pkt_cmd; 8592 lun = *((uint16_t *)cmd); 8593 lun = LE_SWAP16(lun); 8594 8595 iocbq = &sbp->iocbq; 8596 iocb = &iocbq->iocb; 8597 iocbq->node = (void *) ndlp; 8598 8599 /* Check for target reset */ 8600 if (cmd[10] & 0x20) { 8601 /* prepare iocb */ 8602 if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp, 8603 hba->channel_fcp)) != FC_SUCCESS) { 8604 8605 if (rval == 0xff) { 8606 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 8607 0, 1); 8608 rval = FC_SUCCESS; 8609 } 8610 8611 return (rval); 8612 } 8613 8614 mutex_enter(&sbp->mtx); 8615 sbp->pkt_flags |= PACKET_FCP_TGT_RESET; 8616 sbp->pkt_flags |= PACKET_POLLED; 8617 *pkt_flags = sbp->pkt_flags; 8618 mutex_exit(&sbp->mtx); 8619 8620 #ifdef SAN_DIAG_SUPPORT 8621 emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_TGTRESET, 8622 (HBA_WWN *)&ndlp->nlp_portname, -1); 8623 #endif /* SAN_DIAG_SUPPORT */ 8624 8625 iocbq->flag |= IOCB_PRIORITY; 8626 8627 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8628 "Target Reset: did=%x", did); 8629 8630 cfg = &CFG; 8631 if (cfg[CFG_FAST_TGT_RESET].current) { 8632 if (emlxs_fast_target_reset(port, sbp, ndlp) == 8633 FC_SUCCESS) { 8634 return (FC_SUCCESS); 8635 } 8636 } 8637 8638 /* Close the node for any further normal IO */ 8639 emlxs_node_close(port, ndlp, hba->channel_fcp, 8640 pkt->pkt_timeout); 8641 8642 /* Flush the IO's on the tx queues */ 8643 (void) emlxs_tx_node_flush(port, ndlp, 8644 &hba->chan[hba->channel_fcp], 0, sbp); 8645 8646 /* This is the target reset fcp cmd */ 8647 reset = 1; 8648 } 8649 8650 /* Check for lun reset */ 8651 else if (cmd[10] & 0x10) { 8652 /* prepare iocb */ 8653 if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp, 8654 hba->channel_fcp)) != FC_SUCCESS) { 8655 8656 if (rval == 0xff) { 8657 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 8658 0, 1); 8659 rval = FC_SUCCESS; 8660 } 8661 8662 return (rval); 8663 } 8664 8665 mutex_enter(&sbp->mtx); 8666 sbp->pkt_flags |= PACKET_FCP_LUN_RESET; 8667 sbp->pkt_flags |= PACKET_POLLED; 8668 *pkt_flags = sbp->pkt_flags; 8669 mutex_exit(&sbp->mtx); 8670 8671 #ifdef SAN_DIAG_SUPPORT 8672 emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_LUNRESET, 8673 (HBA_WWN *)&ndlp->nlp_portname, lun); 8674 #endif /* SAN_DIAG_SUPPORT */ 8675 8676 iocbq->flag |= IOCB_PRIORITY; 8677 8678 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8679 "LUN Reset: did=%x lun=%02x LUN=%02x02x", did, lun, 8680 cmd[0], cmd[1]); 8681 8682 /* Flush the IO's on the tx queues for this lun */ 8683 (void) emlxs_tx_lun_flush(port, ndlp, lun, sbp); 8684 8685 /* This is the lun reset fcp cmd */ 8686 reset = 1; 8687 } 8688 8689 channel = emlxs_select_fcp_channel(hba, ndlp, reset); 8690 8691 #ifdef SAN_DIAG_SUPPORT 8692 sbp->sd_start_time = gethrtime(); 8693 #endif /* SAN_DIAG_SUPPORT */ 8694 8695 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 8696 emlxs_swap_fcp_pkt(sbp); 8697 #endif /* EMLXS_MODREV2X */ 8698 8699 fcp_cmd = (FCP_CMND *) pkt->pkt_cmd; 8700 8701 if (fcp_cmd->fcpCntl1 == FCP_QTYPE_UNTAGGED) { 8702 fcp_cmd->fcpCntl1 = FCP_QTYPE_SIMPLE; 8703 } 8704 8705 if (reset == 0) { 8706 /* 8707 * tgt lun reset fcp cmd has been prepared 8708 * separately in the beginning 8709 */ 8710 if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp, 8711 channel)) != FC_SUCCESS) { 8712 8713 if (rval == 0xff) { 8714 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 8715 0, 1); 8716 rval = FC_SUCCESS; 8717 } 8718 8719 return (rval); 8720 } 8721 } 8722 8723 cp = &hba->chan[channel]; 8724 cp->ulpSendCmd++; 8725 8726 /* Initalize sbp */ 8727 mutex_enter(&sbp->mtx); 8728 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 8729 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 8730 sbp->node = (void *)ndlp; 8731 sbp->lun = lun; 8732 sbp->class = iocb->ULPCLASS; 8733 sbp->did = ndlp->nlp_DID; 8734 mutex_exit(&sbp->mtx); 8735 8736 if (pkt->pkt_cmdlen) { 8737 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 8738 DDI_DMA_SYNC_FORDEV); 8739 } 8740 8741 if (pkt->pkt_datalen && pkt->pkt_tran_type == FC_PKT_FCP_WRITE) { 8742 EMLXS_MPDATA_SYNC(pkt->pkt_data_dma, 0, pkt->pkt_datalen, 8743 DDI_DMA_SYNC_FORDEV); 8744 } 8745 8746 HBASTATS.FcpIssued++; 8747 8748 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 8749 return (FC_SUCCESS); 8750 8751 } /* emlxs_send_fcp_cmd() */ 8752 8753 8754 8755 8756 /* 8757 * We have to consider this setup works for INTX, MSI, and MSIX 8758 * For INTX, intr_count is always 1 8759 * For MSI, intr_count is always 2 by default 8760 * For MSIX, intr_count is configurable (1, 2, 4, 8) for now. 8761 */ 8762 extern int 8763 emlxs_select_msiid(emlxs_hba_t *hba) 8764 { 8765 int msiid = 0; 8766 8767 /* We use round-robin */ 8768 mutex_enter(&EMLXS_MSIID_LOCK); 8769 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 8770 msiid = hba->last_msiid; 8771 hba->last_msiid ++; 8772 if (hba->last_msiid >= hba->intr_count) { 8773 hba->last_msiid = 0; 8774 } 8775 } else { 8776 /* This should work for INTX and MSI also */ 8777 /* For SLI3 the chan_count is always 4 */ 8778 /* For SLI3 the msiid is limited to chan_count */ 8779 msiid = hba->last_msiid; 8780 hba->last_msiid ++; 8781 if (hba->intr_count > hba->chan_count) { 8782 if (hba->last_msiid >= hba->chan_count) { 8783 hba->last_msiid = 0; 8784 } 8785 } else { 8786 if (hba->last_msiid >= hba->intr_count) { 8787 hba->last_msiid = 0; 8788 } 8789 } 8790 } 8791 mutex_exit(&EMLXS_MSIID_LOCK); 8792 8793 return (msiid); 8794 } /* emlxs_select_msiid */ 8795 8796 8797 /* 8798 * A channel has a association with a msi id. 8799 * One msi id could be associated with multiple channels. 8800 */ 8801 extern int 8802 emlxs_msiid_to_chan(emlxs_hba_t *hba, int msi_id) 8803 { 8804 emlxs_config_t *cfg = &CFG; 8805 EQ_DESC_t *eqp; 8806 int chan; 8807 int num_wq; 8808 8809 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 8810 /* For SLI4 round robin all WQs associated with the msi_id */ 8811 eqp = &hba->sli.sli4.eq[msi_id]; 8812 8813 mutex_enter(&eqp->lastwq_lock); 8814 chan = eqp->lastwq; 8815 eqp->lastwq++; 8816 num_wq = cfg[CFG_NUM_WQ].current; 8817 if (eqp->lastwq >= ((msi_id + 1) * num_wq)) { 8818 eqp->lastwq -= num_wq; 8819 } 8820 mutex_exit(&eqp->lastwq_lock); 8821 8822 return (chan); 8823 } else { 8824 /* This is for SLI3 mode */ 8825 return (hba->msi2chan[msi_id]); 8826 } 8827 8828 } /* emlxs_msiid_to_chan */ 8829 8830 8831 #ifdef SFCT_SUPPORT 8832 static int32_t 8833 emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp) 8834 { 8835 emlxs_hba_t *hba = HBA; 8836 IOCBQ *iocbq; 8837 IOCB *iocb; 8838 NODELIST *ndlp; 8839 CHANNEL *cp; 8840 uint32_t did; 8841 8842 did = sbp->did; 8843 ndlp = sbp->node; 8844 cp = (CHANNEL *)sbp->channel; 8845 8846 iocbq = &sbp->iocbq; 8847 iocb = &iocbq->iocb; 8848 8849 /* Make sure node is still active */ 8850 if (!ndlp->nlp_active) { 8851 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 8852 "*Node not found. did=%x", did); 8853 8854 return (FC_BADPACKET); 8855 } 8856 8857 /* If gate is closed */ 8858 if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) { 8859 return (FC_TRAN_BUSY); 8860 } 8861 8862 iocb->ULPCOMMAND = CMD_FCP_TRSP64_CX; 8863 if (EMLXS_SLI_PREP_FCT_IOCB(port, sbp, cp->channelno) != 8864 IOERR_SUCCESS) { 8865 return (FC_TRAN_BUSY); 8866 } 8867 8868 HBASTATS.FcpIssued++; 8869 8870 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 8871 8872 return (FC_SUCCESS); 8873 8874 } /* emlxs_send_fct_status() */ 8875 8876 8877 static int32_t 8878 emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp) 8879 { 8880 emlxs_hba_t *hba = HBA; 8881 IOCBQ *iocbq; 8882 IOCB *iocb; 8883 NODELIST *ndlp; 8884 CHANNEL *cp; 8885 uint32_t did; 8886 8887 did = sbp->did; 8888 ndlp = sbp->node; 8889 cp = (CHANNEL *)sbp->channel; 8890 8891 iocbq = &sbp->iocbq; 8892 iocb = &iocbq->iocb; 8893 8894 /* Make sure node is still active */ 8895 if ((ndlp == NULL) || (!ndlp->nlp_active)) { 8896 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 8897 "*Node not found. did=%x", did); 8898 8899 return (FC_BADPACKET); 8900 } 8901 8902 /* If gate is closed */ 8903 if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) { 8904 return (FC_TRAN_BUSY); 8905 } 8906 8907 iocb->ULPCOMMAND = CMD_ABORT_XRI_CX; 8908 if (EMLXS_SLI_PREP_FCT_IOCB(port, sbp, cp->channelno) != 8909 IOERR_SUCCESS) { 8910 return (FC_TRAN_BUSY); 8911 } 8912 8913 EMLXS_SLI_ISSUE_IOCB_CMD(hba, sbp->channel, iocbq); 8914 8915 return (FC_SUCCESS); 8916 8917 } /* emlxs_send_fct_abort() */ 8918 8919 #endif /* SFCT_SUPPORT */ 8920 8921 8922 static int32_t 8923 emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp) 8924 { 8925 emlxs_hba_t *hba = HBA; 8926 fc_packet_t *pkt; 8927 IOCBQ *iocbq; 8928 IOCB *iocb; 8929 CHANNEL *cp; 8930 uint32_t i; 8931 NODELIST *ndlp; 8932 uint32_t did; 8933 int32_t rval; 8934 8935 pkt = PRIV2PKT(sbp); 8936 cp = &hba->chan[hba->channel_ip]; 8937 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 8938 8939 /* Check if node exists */ 8940 /* Broadcast did is always a success */ 8941 ndlp = emlxs_node_find_did(port, did, 1); 8942 8943 if (!ndlp || !ndlp->nlp_active) { 8944 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 8945 "Node not found. did=0x%x", did); 8946 8947 return (FC_BADPACKET); 8948 } 8949 8950 /* Check if gate is temporarily closed */ 8951 if (ndlp->nlp_flag[hba->channel_ip] & NLP_CLOSED) { 8952 return (FC_TRAN_BUSY); 8953 } 8954 8955 /* Check if an exchange has been created */ 8956 if ((ndlp->nlp_Xri == 0) && (did != BCAST_DID)) { 8957 /* No exchange. Try creating one */ 8958 (void) emlxs_create_xri(port, cp, ndlp); 8959 8960 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8961 "Adapter Busy. Exchange not found. did=0x%x", did); 8962 8963 return (FC_TRAN_BUSY); 8964 } 8965 8966 /* ULP PATCH: pkt_cmdlen was found to be set to zero */ 8967 /* on BROADCAST commands */ 8968 if (pkt->pkt_cmdlen == 0) { 8969 /* Set the pkt_cmdlen to the cookie size */ 8970 #if (EMLXS_MODREV >= EMLXS_MODREV3) 8971 for (i = 0; i < pkt->pkt_cmd_cookie_cnt; i++) { 8972 pkt->pkt_cmdlen += pkt->pkt_cmd_cookie[i].dmac_size; 8973 } 8974 #else 8975 pkt->pkt_cmdlen = pkt->pkt_cmd_cookie.dmac_size; 8976 #endif /* >= EMLXS_MODREV3 */ 8977 8978 } 8979 8980 iocbq = &sbp->iocbq; 8981 iocb = &iocbq->iocb; 8982 8983 iocbq->node = (void *)ndlp; 8984 if ((rval = EMLXS_SLI_PREP_IP_IOCB(port, sbp)) != FC_SUCCESS) { 8985 8986 if (rval == 0xff) { 8987 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 8988 rval = FC_SUCCESS; 8989 } 8990 8991 return (rval); 8992 } 8993 8994 cp->ulpSendCmd++; 8995 8996 /* Initalize sbp */ 8997 mutex_enter(&sbp->mtx); 8998 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 8999 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 9000 sbp->node = (void *)ndlp; 9001 sbp->lun = EMLXS_LUN_NONE; 9002 sbp->class = iocb->ULPCLASS; 9003 sbp->did = did; 9004 mutex_exit(&sbp->mtx); 9005 9006 if (pkt->pkt_cmdlen) { 9007 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 9008 DDI_DMA_SYNC_FORDEV); 9009 } 9010 9011 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 9012 9013 return (FC_SUCCESS); 9014 9015 } /* emlxs_send_ip() */ 9016 9017 9018 static int32_t 9019 emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) 9020 { 9021 emlxs_hba_t *hba = HBA; 9022 emlxs_port_t *vport; 9023 fc_packet_t *pkt; 9024 IOCBQ *iocbq; 9025 CHANNEL *cp; 9026 SERV_PARM *sp; 9027 uint32_t cmd; 9028 int i; 9029 ELS_PKT *els_pkt; 9030 NODELIST *ndlp; 9031 uint32_t did; 9032 char fcsp_msg[32]; 9033 int rc; 9034 int32_t rval; 9035 emlxs_config_t *cfg = &CFG; 9036 9037 fcsp_msg[0] = 0; 9038 pkt = PRIV2PKT(sbp); 9039 els_pkt = (ELS_PKT *)pkt->pkt_cmd; 9040 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 9041 9042 iocbq = &sbp->iocbq; 9043 9044 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 9045 emlxs_swap_els_pkt(sbp); 9046 #endif /* EMLXS_MODREV2X */ 9047 9048 cmd = *((uint32_t *)pkt->pkt_cmd); 9049 cmd &= ELS_CMD_MASK; 9050 9051 /* Point of no return, except for ADISC & PLOGI */ 9052 9053 /* Check node */ 9054 switch (cmd) { 9055 case ELS_CMD_FLOGI: 9056 case ELS_CMD_FDISC: 9057 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 9058 9059 if (emlxs_vpi_logi_notify(port, sbp)) { 9060 pkt->pkt_state = FC_PKT_LOCAL_RJT; 9061 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 9062 emlxs_unswap_pkt(sbp); 9063 #endif /* EMLXS_MODREV2X */ 9064 return (FC_FAILURE); 9065 } 9066 } else { 9067 /* 9068 * If FLOGI is already complete, then we 9069 * should not be receiving another FLOGI. 9070 * Reset the link to recover. 9071 */ 9072 if (port->flag & EMLXS_PORT_FLOGI_CMPL) { 9073 pkt->pkt_state = FC_PKT_LOCAL_RJT; 9074 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 9075 emlxs_unswap_pkt(sbp); 9076 #endif /* EMLXS_MODREV2X */ 9077 9078 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 9079 return (FC_FAILURE); 9080 } 9081 9082 if (port->vpi > 0) { 9083 *((uint32_t *)pkt->pkt_cmd) = ELS_CMD_FDISC; 9084 } 9085 } 9086 9087 /* Command may have been changed */ 9088 cmd = *((uint32_t *)pkt->pkt_cmd); 9089 cmd &= ELS_CMD_MASK; 9090 9091 if (hba->flag & FC_NPIV_DELAY_REQUIRED) { 9092 sbp->pkt_flags |= PACKET_DELAY_REQUIRED; 9093 } 9094 9095 ndlp = NULL; 9096 9097 /* We will process these cmds at the bottom of this routine */ 9098 break; 9099 9100 case ELS_CMD_PLOGI: 9101 /* Make sure we don't log into ourself */ 9102 for (i = 0; i < MAX_VPORTS; i++) { 9103 vport = &VPORT(i); 9104 9105 if (!(vport->flag & EMLXS_INI_BOUND)) { 9106 continue; 9107 } 9108 9109 if (did == vport->did) { 9110 pkt->pkt_state = FC_PKT_NPORT_RJT; 9111 9112 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 9113 emlxs_unswap_pkt(sbp); 9114 #endif /* EMLXS_MODREV2X */ 9115 9116 return (FC_FAILURE); 9117 } 9118 } 9119 9120 ndlp = NULL; 9121 9122 if (hba->flag & FC_PT_TO_PT) { 9123 MAILBOXQ *mbox; 9124 9125 /* ULP bug fix */ 9126 if (pkt->pkt_cmd_fhdr.s_id == 0) { 9127 pkt->pkt_cmd_fhdr.s_id = FP_DEFAULT_SID; 9128 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_send_msg, 9129 "PLOGI: P2P Fix. sid=0-->%x did=%x", 9130 pkt->pkt_cmd_fhdr.s_id, 9131 pkt->pkt_cmd_fhdr.d_id); 9132 } 9133 9134 mutex_enter(&EMLXS_PORT_LOCK); 9135 port->did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.s_id); 9136 port->rdid = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 9137 mutex_exit(&EMLXS_PORT_LOCK); 9138 9139 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 9140 /* Update our service parms */ 9141 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 9142 MEM_MBOX))) { 9143 emlxs_mb_config_link(hba, mbox); 9144 9145 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, 9146 mbox, MBX_NOWAIT, 0); 9147 if ((rc != MBX_BUSY) && 9148 (rc != MBX_SUCCESS)) { 9149 emlxs_mem_put(hba, MEM_MBOX, 9150 (void *)mbox); 9151 } 9152 } 9153 } 9154 } 9155 9156 /* We will process these cmds at the bottom of this routine */ 9157 break; 9158 9159 default: 9160 ndlp = emlxs_node_find_did(port, did, 1); 9161 9162 /* If an ADISC is being sent and we have no node, */ 9163 /* then we must fail the ADISC now */ 9164 if (!ndlp && (cmd == ELS_CMD_ADISC) && 9165 (port->mode == MODE_INITIATOR)) { 9166 9167 /* Build the LS_RJT response */ 9168 els_pkt = (ELS_PKT *)pkt->pkt_resp; 9169 els_pkt->elsCode = 0x01; 9170 els_pkt->un.lsRjt.un.b.lsRjtRsvd0 = 0; 9171 els_pkt->un.lsRjt.un.b.lsRjtRsnCode = 9172 LSRJT_LOGICAL_ERR; 9173 els_pkt->un.lsRjt.un.b.lsRjtRsnCodeExp = 9174 LSEXP_NOTHING_MORE; 9175 els_pkt->un.lsRjt.un.b.vendorUnique = 0x03; 9176 9177 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 9178 "ADISC Rejected. Node not found. did=0x%x", did); 9179 9180 if (sbp->channel == NULL) { 9181 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 9182 sbp->channel = 9183 &hba->chan[hba->channel_els]; 9184 } else { 9185 sbp->channel = 9186 &hba->chan[FC_ELS_RING]; 9187 } 9188 } 9189 9190 /* Return this as rejected by the target */ 9191 emlxs_pkt_complete(sbp, IOSTAT_LS_RJT, 0, 1); 9192 9193 return (FC_SUCCESS); 9194 } 9195 } 9196 9197 /* DID == BCAST_DID is special case to indicate that */ 9198 /* RPI is being passed in seq_id field */ 9199 /* This is used by emlxs_send_logo() for target mode */ 9200 9201 /* Initalize iocbq */ 9202 iocbq->node = (void *)ndlp; 9203 if ((rval = EMLXS_SLI_PREP_ELS_IOCB(port, sbp)) != FC_SUCCESS) { 9204 9205 if (rval == 0xff) { 9206 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 9207 rval = FC_SUCCESS; 9208 } 9209 9210 return (rval); 9211 } 9212 9213 cp = &hba->chan[hba->channel_els]; 9214 cp->ulpSendCmd++; 9215 sp = (SERV_PARM *)&els_pkt->un.logi; 9216 9217 /* Check cmd */ 9218 switch (cmd) { 9219 case ELS_CMD_PRLI: 9220 /* 9221 * if our firmware version is 3.20 or later, 9222 * set the following bits for FC-TAPE support. 9223 */ 9224 if ((port->mode == MODE_INITIATOR) && 9225 (hba->vpd.feaLevelHigh >= 0x02) && 9226 (cfg[CFG_ADISC_SUPPORT].current != 0)) { 9227 els_pkt->un.prli.ConfmComplAllowed = 1; 9228 els_pkt->un.prli.Retry = 1; 9229 els_pkt->un.prli.TaskRetryIdReq = 1; 9230 } else { 9231 els_pkt->un.prli.ConfmComplAllowed = 0; 9232 els_pkt->un.prli.Retry = 0; 9233 els_pkt->un.prli.TaskRetryIdReq = 0; 9234 } 9235 9236 break; 9237 9238 /* This is a patch for the ULP stack. */ 9239 9240 /* 9241 * ULP only reads our service parameters once during bind_port, 9242 * but the service parameters change due to topology. 9243 */ 9244 case ELS_CMD_FLOGI: 9245 case ELS_CMD_FDISC: 9246 case ELS_CMD_PLOGI: 9247 case ELS_CMD_PDISC: 9248 /* Copy latest service parameters to payload */ 9249 bcopy((void *) &port->sparam, (void *)sp, sizeof (SERV_PARM)); 9250 9251 if ((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) { 9252 9253 /* Clear support for virtual fabrics */ 9254 /* randomOffset bit controls this for FLOGI */ 9255 sp->cmn.randomOffset = 0; 9256 9257 /* Set R_A_TOV to current value */ 9258 sp->cmn.w2.r_a_tov = 9259 LE_SWAP32((hba->fc_ratov * 1000)); 9260 } 9261 9262 if ((hba->flag & FC_NPIV_ENABLED) && 9263 (hba->flag & FC_NPIV_SUPPORTED) && 9264 (cmd == ELS_CMD_PLOGI)) { 9265 emlxs_vvl_fmt_t *vvl; 9266 9267 sp->VALID_VENDOR_VERSION = 1; 9268 vvl = (emlxs_vvl_fmt_t *)&sp->vendorVersion[0]; 9269 vvl->un0.w0.oui = 0x0000C9; 9270 vvl->un0.word0 = LE_SWAP32(vvl->un0.word0); 9271 vvl->un1.w1.vport = (port->vpi > 0) ? 1 : 0; 9272 vvl->un1.word1 = LE_SWAP32(vvl->un1.word1); 9273 } 9274 9275 #ifdef DHCHAP_SUPPORT 9276 emlxs_dhc_init_sp(port, did, sp, (char **)&fcsp_msg); 9277 #endif /* DHCHAP_SUPPORT */ 9278 9279 break; 9280 } 9281 9282 /* Initialize the sbp */ 9283 mutex_enter(&sbp->mtx); 9284 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 9285 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 9286 sbp->node = (void *)ndlp; 9287 sbp->lun = EMLXS_LUN_NONE; 9288 sbp->did = did; 9289 mutex_exit(&sbp->mtx); 9290 9291 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_send_msg, "%s: sid=%x did=%x %s", 9292 emlxs_elscmd_xlate(cmd), port->did, did, fcsp_msg); 9293 9294 if (pkt->pkt_cmdlen) { 9295 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 9296 DDI_DMA_SYNC_FORDEV); 9297 } 9298 9299 /* Check node */ 9300 switch (cmd) { 9301 case ELS_CMD_FLOGI: 9302 case ELS_CMD_FDISC: 9303 if (port->mode == MODE_INITIATOR) { 9304 /* Make sure fabric node is destroyed */ 9305 /* It should already have been destroyed at link down */ 9306 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 9307 ndlp = emlxs_node_find_did(port, FABRIC_DID, 1); 9308 if (ndlp) { 9309 if (EMLXS_SLI_UNREG_NODE(port, ndlp, 9310 NULL, NULL, iocbq) == 0) { 9311 /* Deferring iocb tx until */ 9312 /* completion of unreg */ 9313 return (FC_SUCCESS); 9314 } 9315 } 9316 } 9317 } 9318 break; 9319 9320 case ELS_CMD_PLOGI: 9321 9322 ndlp = emlxs_node_find_did(port, did, 1); 9323 9324 if (ndlp && ndlp->nlp_active) { 9325 /* Close the node for any further normal IO */ 9326 emlxs_node_close(port, ndlp, hba->channel_fcp, 9327 pkt->pkt_timeout + 10); 9328 emlxs_node_close(port, ndlp, hba->channel_ip, 9329 pkt->pkt_timeout + 10); 9330 9331 /* Flush tx queues */ 9332 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); 9333 9334 /* Flush chip queues */ 9335 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0); 9336 } 9337 9338 break; 9339 9340 case ELS_CMD_PRLI: 9341 9342 ndlp = emlxs_node_find_did(port, did, 1); 9343 9344 if (ndlp && ndlp->nlp_active) { 9345 /* 9346 * Close the node for any further FCP IO; 9347 * Flush all outstanding I/O only if 9348 * "Establish Image Pair" bit is set. 9349 */ 9350 emlxs_node_close(port, ndlp, hba->channel_fcp, 9351 pkt->pkt_timeout + 10); 9352 9353 if (els_pkt->un.prli.estabImagePair) { 9354 /* Flush tx queues */ 9355 (void) emlxs_tx_node_flush(port, ndlp, 9356 &hba->chan[hba->channel_fcp], 0, 0); 9357 9358 /* Flush chip queues */ 9359 (void) emlxs_chipq_node_flush(port, 9360 &hba->chan[hba->channel_fcp], ndlp, 0); 9361 } 9362 } 9363 9364 break; 9365 9366 } 9367 9368 HBASTATS.ElsCmdIssued++; 9369 9370 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 9371 9372 return (FC_SUCCESS); 9373 9374 } /* emlxs_send_els() */ 9375 9376 9377 9378 9379 static int32_t 9380 emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp) 9381 { 9382 emlxs_hba_t *hba = HBA; 9383 emlxs_config_t *cfg = &CFG; 9384 fc_packet_t *pkt; 9385 IOCBQ *iocbq; 9386 IOCB *iocb; 9387 NODELIST *ndlp; 9388 CHANNEL *cp; 9389 int i; 9390 uint32_t cmd; 9391 uint32_t ucmd; 9392 ELS_PKT *els_pkt; 9393 fc_unsol_buf_t *ubp; 9394 emlxs_ub_priv_t *ub_priv; 9395 uint32_t did; 9396 char fcsp_msg[32]; 9397 uint8_t *ub_buffer; 9398 int32_t rval; 9399 9400 fcsp_msg[0] = 0; 9401 pkt = PRIV2PKT(sbp); 9402 els_pkt = (ELS_PKT *)pkt->pkt_cmd; 9403 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 9404 9405 iocbq = &sbp->iocbq; 9406 iocb = &iocbq->iocb; 9407 9408 /* Acquire the unsolicited command this pkt is replying to */ 9409 if (pkt->pkt_cmd_fhdr.ox_id < EMLXS_UB_TOKEN_OFFSET) { 9410 /* This is for auto replies when no ub's are used */ 9411 ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT; 9412 ubp = NULL; 9413 ub_priv = NULL; 9414 ub_buffer = NULL; 9415 9416 #ifdef SFCT_SUPPORT 9417 if (sbp->fct_cmd) { 9418 fct_els_t *els = 9419 (fct_els_t *)sbp->fct_cmd->cmd_specific; 9420 ub_buffer = (uint8_t *)els->els_req_payload; 9421 } 9422 #endif /* SFCT_SUPPORT */ 9423 9424 } else { 9425 /* Find the ub buffer that goes with this reply */ 9426 if (!(ubp = emlxs_ub_find(port, pkt->pkt_cmd_fhdr.ox_id))) { 9427 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 9428 "ELS reply: Invalid oxid=%x", 9429 pkt->pkt_cmd_fhdr.ox_id); 9430 return (FC_BADPACKET); 9431 } 9432 9433 ub_buffer = (uint8_t *)ubp->ub_buffer; 9434 ub_priv = ubp->ub_fca_private; 9435 ucmd = ub_priv->cmd; 9436 9437 ub_priv->flags |= EMLXS_UB_REPLY; 9438 9439 /* Reset oxid to ELS command */ 9440 /* We do this because the ub is only valid */ 9441 /* until we return from this thread */ 9442 pkt->pkt_cmd_fhdr.ox_id = (ucmd >> ELS_CMD_SHIFT) & 0xff; 9443 } 9444 9445 /* Save the result */ 9446 sbp->ucmd = ucmd; 9447 9448 if (sbp->channel == NULL) { 9449 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 9450 sbp->channel = &hba->chan[hba->channel_els]; 9451 } else { 9452 sbp->channel = &hba->chan[FC_ELS_RING]; 9453 } 9454 } 9455 9456 /* Check for interceptions */ 9457 switch (ucmd) { 9458 9459 #ifdef ULP_PATCH2 9460 case ELS_CMD_LOGO: 9461 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH2)) { 9462 break; 9463 } 9464 9465 /* Check if this was generated by ULP and not us */ 9466 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) { 9467 9468 /* 9469 * Since we replied to this already, 9470 * we won't need to send this now 9471 */ 9472 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 9473 9474 return (FC_SUCCESS); 9475 } 9476 9477 break; 9478 #endif /* ULP_PATCH2 */ 9479 9480 #ifdef ULP_PATCH3 9481 case ELS_CMD_PRLI: 9482 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH3)) { 9483 break; 9484 } 9485 9486 /* Check if this was generated by ULP and not us */ 9487 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) { 9488 9489 /* 9490 * Since we replied to this already, 9491 * we won't need to send this now 9492 */ 9493 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 9494 9495 return (FC_SUCCESS); 9496 } 9497 9498 break; 9499 #endif /* ULP_PATCH3 */ 9500 9501 9502 #ifdef ULP_PATCH4 9503 case ELS_CMD_PRLO: 9504 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH4)) { 9505 break; 9506 } 9507 9508 /* Check if this was generated by ULP and not us */ 9509 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) { 9510 /* 9511 * Since we replied to this already, 9512 * we won't need to send this now 9513 */ 9514 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 9515 9516 return (FC_SUCCESS); 9517 } 9518 9519 break; 9520 #endif /* ULP_PATCH4 */ 9521 9522 #ifdef ULP_PATCH6 9523 case ELS_CMD_RSCN: 9524 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH6)) { 9525 break; 9526 } 9527 9528 /* Check if this RSCN was generated by us */ 9529 if (ub_priv && (ub_priv->flags & EMLXS_UB_INTERCEPT)) { 9530 cmd = *((uint32_t *)pkt->pkt_cmd); 9531 cmd = LE_SWAP32(cmd); 9532 cmd &= ELS_CMD_MASK; 9533 9534 /* 9535 * If ULP is accepting this, 9536 * then close affected node 9537 */ 9538 if ((port->mode == MODE_INITIATOR) && ub_buffer && 9539 cmd == ELS_CMD_ACC) { 9540 fc_rscn_t *rscn; 9541 uint32_t count; 9542 uint32_t *lp; 9543 9544 /* 9545 * Only the Leadville code path will 9546 * come thru here. The RSCN data is NOT 9547 * swapped properly for the Comstar code 9548 * path. 9549 */ 9550 lp = (uint32_t *)ub_buffer; 9551 rscn = (fc_rscn_t *)lp++; 9552 count = 9553 ((rscn->rscn_payload_len - 4) / 4); 9554 9555 /* Close affected ports */ 9556 for (i = 0; i < count; i++, lp++) { 9557 (void) emlxs_port_offline(port, 9558 *lp); 9559 } 9560 } 9561 9562 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg, 9563 "RSCN %s: did=%x oxid=%x rxid=%x. " 9564 "Intercepted.", emlxs_elscmd_xlate(cmd), 9565 did, pkt->pkt_cmd_fhdr.ox_id, 9566 pkt->pkt_cmd_fhdr.rx_id); 9567 9568 /* 9569 * Since we generated this RSCN, 9570 * we won't need to send this reply 9571 */ 9572 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 9573 9574 return (FC_SUCCESS); 9575 } 9576 9577 break; 9578 #endif /* ULP_PATCH6 */ 9579 9580 case ELS_CMD_PLOGI: 9581 /* Check if this PLOGI was generated by us */ 9582 if (ub_priv && (ub_priv->flags & EMLXS_UB_INTERCEPT)) { 9583 cmd = *((uint32_t *)pkt->pkt_cmd); 9584 cmd = LE_SWAP32(cmd); 9585 cmd &= ELS_CMD_MASK; 9586 9587 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg, 9588 "PLOGI %s: did=%x oxid=%x rxid=%x. " 9589 "Intercepted.", emlxs_elscmd_xlate(cmd), 9590 did, pkt->pkt_cmd_fhdr.ox_id, 9591 pkt->pkt_cmd_fhdr.rx_id); 9592 9593 /* 9594 * Since we generated this PLOGI, 9595 * we won't need to send this reply 9596 */ 9597 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 9598 9599 return (FC_SUCCESS); 9600 } 9601 9602 break; 9603 } 9604 9605 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 9606 emlxs_swap_els_pkt(sbp); 9607 #endif /* EMLXS_MODREV2X */ 9608 9609 9610 cmd = *((uint32_t *)pkt->pkt_cmd); 9611 cmd &= ELS_CMD_MASK; 9612 9613 /* Check if modifications are needed */ 9614 switch (ucmd) { 9615 case (ELS_CMD_PRLI): 9616 9617 if (cmd == ELS_CMD_ACC) { 9618 /* This is a patch for the ULP stack. */ 9619 /* ULP does not keep track of FCP2 support */ 9620 if ((port->mode == MODE_INITIATOR) && 9621 (hba->vpd.feaLevelHigh >= 0x02) && 9622 (cfg[CFG_ADISC_SUPPORT].current != 0)) { 9623 els_pkt->un.prli.ConfmComplAllowed = 1; 9624 els_pkt->un.prli.Retry = 1; 9625 els_pkt->un.prli.TaskRetryIdReq = 1; 9626 } else { 9627 els_pkt->un.prli.ConfmComplAllowed = 0; 9628 els_pkt->un.prli.Retry = 0; 9629 els_pkt->un.prli.TaskRetryIdReq = 0; 9630 } 9631 } 9632 9633 break; 9634 9635 case ELS_CMD_FLOGI: 9636 case ELS_CMD_FDISC: 9637 if (cmd == ELS_CMD_ACC) { 9638 SERV_PARM *sp = (SERV_PARM *)&els_pkt->un.logi; 9639 9640 /* This is a patch for the ULP stack. */ 9641 9642 /* 9643 * ULP only reads our service parameters 9644 * once during bind_port, but the service 9645 * parameters change due to topology. 9646 */ 9647 9648 /* Copy latest service parameters to payload */ 9649 bcopy((void *)&port->sparam, 9650 (void *)sp, sizeof (SERV_PARM)); 9651 9652 /* We are in pt-to-pt mode. Set R_A_TOV to default */ 9653 sp->cmn.w2.r_a_tov = 9654 LE_SWAP32((FF_DEF_RATOV * 1000)); 9655 9656 /* Clear support for virtual fabrics */ 9657 /* randomOffset bit controls this for FLOGI */ 9658 sp->cmn.randomOffset = 0; 9659 #ifdef DHCHAP_SUPPORT 9660 emlxs_dhc_init_sp(port, did, sp, (char **)&fcsp_msg); 9661 #endif /* DHCHAP_SUPPORT */ 9662 } 9663 break; 9664 9665 case ELS_CMD_PLOGI: 9666 case ELS_CMD_PDISC: 9667 if (cmd == ELS_CMD_ACC) { 9668 SERV_PARM *sp = (SERV_PARM *)&els_pkt->un.logi; 9669 9670 /* This is a patch for the ULP stack. */ 9671 9672 /* 9673 * ULP only reads our service parameters 9674 * once during bind_port, but the service 9675 * parameters change due to topology. 9676 */ 9677 9678 /* Copy latest service parameters to payload */ 9679 bcopy((void *)&port->sparam, 9680 (void *)sp, sizeof (SERV_PARM)); 9681 9682 #ifdef DHCHAP_SUPPORT 9683 emlxs_dhc_init_sp(port, did, sp, (char **)&fcsp_msg); 9684 #endif /* DHCHAP_SUPPORT */ 9685 } 9686 break; 9687 9688 } 9689 9690 /* Initalize iocbq */ 9691 iocbq->node = (void *)NULL; 9692 if ((rval = EMLXS_SLI_PREP_ELS_IOCB(port, sbp)) != FC_SUCCESS) { 9693 9694 if (rval == 0xff) { 9695 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 9696 rval = FC_SUCCESS; 9697 } 9698 9699 return (rval); 9700 } 9701 9702 cp = &hba->chan[hba->channel_els]; 9703 cp->ulpSendCmd++; 9704 9705 /* Initalize sbp */ 9706 mutex_enter(&sbp->mtx); 9707 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 9708 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 9709 sbp->node = (void *) NULL; 9710 sbp->lun = EMLXS_LUN_NONE; 9711 sbp->class = iocb->ULPCLASS; 9712 sbp->did = did; 9713 mutex_exit(&sbp->mtx); 9714 9715 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg, 9716 "%s %s: did=%x oxid=%x rxid=%x %s", emlxs_elscmd_xlate(ucmd), 9717 emlxs_elscmd_xlate(cmd), did, pkt->pkt_cmd_fhdr.ox_id, 9718 pkt->pkt_cmd_fhdr.rx_id, fcsp_msg); 9719 9720 /* Process nodes */ 9721 switch (ucmd) { 9722 case ELS_CMD_RSCN: 9723 if ((port->mode == MODE_INITIATOR) && ub_buffer && 9724 cmd == ELS_CMD_ACC) { 9725 fc_rscn_t *rscn; 9726 uint32_t count; 9727 uint32_t *lp = NULL; 9728 9729 /* 9730 * Only the Leadville code path will come thru 9731 * here. The RSCN data is NOT swapped properly 9732 * for the Comstar code path. 9733 */ 9734 lp = (uint32_t *)ub_buffer; 9735 rscn = (fc_rscn_t *)lp++; 9736 count = ((rscn->rscn_payload_len - 4) / 4); 9737 9738 /* Close affected ports */ 9739 for (i = 0; i < count; i++, lp++) { 9740 (void) emlxs_port_offline(port, *lp); 9741 } 9742 } 9743 break; 9744 9745 case ELS_CMD_PLOGI: 9746 if (cmd == ELS_CMD_ACC) { 9747 ndlp = emlxs_node_find_did(port, did, 1); 9748 9749 if (ndlp && ndlp->nlp_active) { 9750 /* Close the node for any further normal IO */ 9751 emlxs_node_close(port, ndlp, hba->channel_fcp, 9752 pkt->pkt_timeout + 10); 9753 emlxs_node_close(port, ndlp, hba->channel_ip, 9754 pkt->pkt_timeout + 10); 9755 9756 /* Flush tx queue */ 9757 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); 9758 9759 /* Flush chip queue */ 9760 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0); 9761 } 9762 } 9763 break; 9764 9765 case ELS_CMD_PRLI: 9766 if (cmd == ELS_CMD_ACC) { 9767 ndlp = emlxs_node_find_did(port, did, 1); 9768 9769 if (ndlp && ndlp->nlp_active) { 9770 /* Close the node for any further normal IO */ 9771 emlxs_node_close(port, ndlp, hba->channel_fcp, 9772 pkt->pkt_timeout + 10); 9773 9774 /* Flush tx queues */ 9775 (void) emlxs_tx_node_flush(port, ndlp, 9776 &hba->chan[hba->channel_fcp], 0, 0); 9777 9778 /* Flush chip queues */ 9779 (void) emlxs_chipq_node_flush(port, 9780 &hba->chan[hba->channel_fcp], ndlp, 0); 9781 } 9782 } 9783 break; 9784 9785 case ELS_CMD_PRLO: 9786 if (cmd == ELS_CMD_ACC) { 9787 ndlp = emlxs_node_find_did(port, did, 1); 9788 9789 if (ndlp && ndlp->nlp_active) { 9790 /* Close the node for any further normal IO */ 9791 emlxs_node_close(port, ndlp, 9792 hba->channel_fcp, 60); 9793 9794 /* Flush tx queues */ 9795 (void) emlxs_tx_node_flush(port, ndlp, 9796 &hba->chan[hba->channel_fcp], 0, 0); 9797 9798 /* Flush chip queues */ 9799 (void) emlxs_chipq_node_flush(port, 9800 &hba->chan[hba->channel_fcp], ndlp, 0); 9801 } 9802 } 9803 9804 break; 9805 9806 case ELS_CMD_LOGO: 9807 if (cmd == ELS_CMD_ACC) { 9808 ndlp = emlxs_node_find_did(port, did, 1); 9809 9810 if (ndlp && ndlp->nlp_active) { 9811 /* Close the node for any further normal IO */ 9812 emlxs_node_close(port, ndlp, 9813 hba->channel_fcp, 60); 9814 emlxs_node_close(port, ndlp, 9815 hba->channel_ip, 60); 9816 9817 /* Flush tx queues */ 9818 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); 9819 9820 /* Flush chip queues */ 9821 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0); 9822 } 9823 } 9824 9825 break; 9826 } 9827 9828 if (pkt->pkt_cmdlen) { 9829 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 9830 DDI_DMA_SYNC_FORDEV); 9831 } 9832 9833 HBASTATS.ElsRspIssued++; 9834 9835 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 9836 9837 return (FC_SUCCESS); 9838 9839 } /* emlxs_send_els_rsp() */ 9840 9841 9842 #ifdef MENLO_SUPPORT 9843 static int32_t 9844 emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp) 9845 { 9846 emlxs_hba_t *hba = HBA; 9847 fc_packet_t *pkt; 9848 IOCBQ *iocbq; 9849 IOCB *iocb; 9850 CHANNEL *cp; 9851 NODELIST *ndlp; 9852 uint32_t did; 9853 uint32_t *lp; 9854 int32_t rval; 9855 9856 pkt = PRIV2PKT(sbp); 9857 did = EMLXS_MENLO_DID; 9858 lp = (uint32_t *)pkt->pkt_cmd; 9859 9860 iocbq = &sbp->iocbq; 9861 iocb = &iocbq->iocb; 9862 9863 ndlp = emlxs_node_find_did(port, did, 1); 9864 9865 if (!ndlp || !ndlp->nlp_active) { 9866 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 9867 "Node not found. did=0x%x", did); 9868 9869 return (FC_BADPACKET); 9870 } 9871 9872 iocbq->node = (void *) ndlp; 9873 if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) { 9874 9875 if (rval == 0xff) { 9876 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 9877 rval = FC_SUCCESS; 9878 } 9879 9880 return (rval); 9881 } 9882 9883 cp = &hba->chan[hba->channel_ct]; 9884 cp->ulpSendCmd++; 9885 9886 if (pkt->pkt_tran_type == FC_PKT_EXCHANGE) { 9887 /* Cmd phase */ 9888 9889 /* Initalize iocb */ 9890 iocb->un.genreq64.param = pkt->pkt_cmd_fhdr.d_id; 9891 iocb->ULPCONTEXT = 0; 9892 iocb->ULPPU = 3; 9893 9894 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 9895 "%s: [%08x,%08x,%08x,%08x]", 9896 emlxs_menlo_cmd_xlate(BE_SWAP32(lp[0])), BE_SWAP32(lp[1]), 9897 BE_SWAP32(lp[2]), BE_SWAP32(lp[3]), BE_SWAP32(lp[4])); 9898 9899 } else { /* FC_PKT_OUTBOUND */ 9900 9901 /* MENLO_CMD_FW_DOWNLOAD Data Phase */ 9902 iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX; 9903 9904 /* Initalize iocb */ 9905 iocb->un.genreq64.param = 0; 9906 iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id; 9907 iocb->ULPPU = 1; 9908 9909 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 9910 "%s: Data: rxid=0x%x size=%d", 9911 emlxs_menlo_cmd_xlate(MENLO_CMD_FW_DOWNLOAD), 9912 pkt->pkt_cmd_fhdr.rx_id, pkt->pkt_cmdlen); 9913 } 9914 9915 /* Initalize sbp */ 9916 mutex_enter(&sbp->mtx); 9917 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 9918 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 9919 sbp->node = (void *) ndlp; 9920 sbp->lun = EMLXS_LUN_NONE; 9921 sbp->class = iocb->ULPCLASS; 9922 sbp->did = did; 9923 mutex_exit(&sbp->mtx); 9924 9925 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 9926 DDI_DMA_SYNC_FORDEV); 9927 9928 HBASTATS.CtCmdIssued++; 9929 9930 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 9931 9932 return (FC_SUCCESS); 9933 9934 } /* emlxs_send_menlo() */ 9935 #endif /* MENLO_SUPPORT */ 9936 9937 9938 static int32_t 9939 emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp) 9940 { 9941 emlxs_hba_t *hba = HBA; 9942 fc_packet_t *pkt; 9943 IOCBQ *iocbq; 9944 IOCB *iocb; 9945 NODELIST *ndlp; 9946 uint32_t did; 9947 CHANNEL *cp; 9948 int32_t rval; 9949 9950 pkt = PRIV2PKT(sbp); 9951 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 9952 9953 iocbq = &sbp->iocbq; 9954 iocb = &iocbq->iocb; 9955 9956 ndlp = emlxs_node_find_did(port, did, 1); 9957 9958 if (!ndlp || !ndlp->nlp_active) { 9959 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 9960 "Node not found. did=0x%x", did); 9961 9962 return (FC_BADPACKET); 9963 } 9964 9965 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 9966 emlxs_swap_ct_pkt(sbp); 9967 #endif /* EMLXS_MODREV2X */ 9968 9969 iocbq->node = (void *)ndlp; 9970 if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) { 9971 9972 if (rval == 0xff) { 9973 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 9974 rval = FC_SUCCESS; 9975 } 9976 9977 return (rval); 9978 } 9979 9980 cp = &hba->chan[hba->channel_ct]; 9981 cp->ulpSendCmd++; 9982 9983 /* Initalize sbp */ 9984 mutex_enter(&sbp->mtx); 9985 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 9986 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 9987 sbp->node = (void *)ndlp; 9988 sbp->lun = EMLXS_LUN_NONE; 9989 sbp->class = iocb->ULPCLASS; 9990 sbp->did = did; 9991 mutex_exit(&sbp->mtx); 9992 9993 if (did == NAMESERVER_DID) { 9994 SLI_CT_REQUEST *CtCmd; 9995 uint32_t *lp0; 9996 9997 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd; 9998 lp0 = (uint32_t *)pkt->pkt_cmd; 9999 10000 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 10001 "%s: did=%x [%08x,%08x]", 10002 emlxs_ctcmd_xlate( 10003 LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)), 10004 did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5])); 10005 10006 if (hba->flag & FC_NPIV_DELAY_REQUIRED) { 10007 sbp->pkt_flags |= PACKET_DELAY_REQUIRED; 10008 } 10009 10010 } else if (did == FDMI_DID) { 10011 SLI_CT_REQUEST *CtCmd; 10012 uint32_t *lp0; 10013 10014 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd; 10015 lp0 = (uint32_t *)pkt->pkt_cmd; 10016 10017 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 10018 "%s: did=%x [%08x,%08x]", 10019 emlxs_mscmd_xlate( 10020 LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)), 10021 did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5])); 10022 } else { 10023 SLI_CT_REQUEST *CtCmd; 10024 uint32_t *lp0; 10025 10026 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd; 10027 lp0 = (uint32_t *)pkt->pkt_cmd; 10028 10029 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 10030 "%s: did=%x [%08x,%08x]", 10031 emlxs_rmcmd_xlate( 10032 LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)), 10033 did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5])); 10034 } 10035 10036 if (pkt->pkt_cmdlen) { 10037 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 10038 DDI_DMA_SYNC_FORDEV); 10039 } 10040 10041 HBASTATS.CtCmdIssued++; 10042 10043 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 10044 10045 return (FC_SUCCESS); 10046 10047 } /* emlxs_send_ct() */ 10048 10049 10050 static int32_t 10051 emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp) 10052 { 10053 emlxs_hba_t *hba = HBA; 10054 fc_packet_t *pkt; 10055 CHANNEL *cp; 10056 IOCBQ *iocbq; 10057 IOCB *iocb; 10058 uint32_t *cmd; 10059 SLI_CT_REQUEST *CtCmd; 10060 int32_t rval; 10061 10062 pkt = PRIV2PKT(sbp); 10063 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd; 10064 cmd = (uint32_t *)pkt->pkt_cmd; 10065 10066 iocbq = &sbp->iocbq; 10067 iocb = &iocbq->iocb; 10068 10069 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 10070 emlxs_swap_ct_pkt(sbp); 10071 #endif /* EMLXS_MODREV2X */ 10072 10073 if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) { 10074 10075 if (rval == 0xff) { 10076 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 10077 rval = FC_SUCCESS; 10078 } 10079 10080 return (rval); 10081 } 10082 10083 cp = &hba->chan[hba->channel_ct]; 10084 cp->ulpSendCmd++; 10085 10086 /* Initalize sbp */ 10087 mutex_enter(&sbp->mtx); 10088 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 10089 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 10090 sbp->node = NULL; 10091 sbp->lun = EMLXS_LUN_NONE; 10092 sbp->class = iocb->ULPCLASS; 10093 mutex_exit(&sbp->mtx); 10094 10095 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_reply_msg, 10096 "%s: Rsn=%x Exp=%x [%08x,%08x] rxid=%x ", 10097 emlxs_rmcmd_xlate(LE_SWAP16( 10098 CtCmd->CommandResponse.bits.CmdRsp)), 10099 CtCmd->ReasonCode, CtCmd->Explanation, 10100 LE_SWAP32(cmd[4]), LE_SWAP32(cmd[5]), 10101 pkt->pkt_cmd_fhdr.rx_id); 10102 10103 if (pkt->pkt_cmdlen) { 10104 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 10105 DDI_DMA_SYNC_FORDEV); 10106 } 10107 10108 HBASTATS.CtRspIssued++; 10109 10110 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 10111 10112 return (FC_SUCCESS); 10113 10114 } /* emlxs_send_ct_rsp() */ 10115 10116 10117 /* 10118 * emlxs_get_instance() 10119 * Given a ddi ddiinst, return a Fibre Channel (emlx) ddiinst. 10120 */ 10121 extern uint32_t 10122 emlxs_get_instance(int32_t ddiinst) 10123 { 10124 uint32_t i; 10125 uint32_t inst; 10126 10127 mutex_enter(&emlxs_device.lock); 10128 10129 inst = MAX_FC_BRDS; 10130 for (i = 0; i < emlxs_instance_count; i++) { 10131 if (emlxs_instance[i] == ddiinst) { 10132 inst = i; 10133 break; 10134 } 10135 } 10136 10137 mutex_exit(&emlxs_device.lock); 10138 10139 return (inst); 10140 10141 } /* emlxs_get_instance() */ 10142 10143 10144 /* 10145 * emlxs_add_instance() 10146 * Given a ddi ddiinst, create a Fibre Channel (emlx) ddiinst. 10147 * emlx ddiinsts are the order that emlxs_attach gets called, starting at 0. 10148 */ 10149 static uint32_t 10150 emlxs_add_instance(int32_t ddiinst) 10151 { 10152 uint32_t i; 10153 10154 mutex_enter(&emlxs_device.lock); 10155 10156 /* First see if the ddiinst already exists */ 10157 for (i = 0; i < emlxs_instance_count; i++) { 10158 if (emlxs_instance[i] == ddiinst) { 10159 break; 10160 } 10161 } 10162 10163 /* If it doesn't already exist, add it */ 10164 if (i >= emlxs_instance_count) { 10165 if ((i = emlxs_instance_count) < MAX_FC_BRDS) { 10166 emlxs_instance[i] = ddiinst; 10167 emlxs_instance_count++; 10168 emlxs_device.hba_count = emlxs_instance_count; 10169 } 10170 } 10171 10172 mutex_exit(&emlxs_device.lock); 10173 10174 return (i); 10175 10176 } /* emlxs_add_instance() */ 10177 10178 10179 /*ARGSUSED*/ 10180 extern void 10181 emlxs_pkt_complete(emlxs_buf_t *sbp, uint32_t iostat, uint8_t localstat, 10182 uint32_t doneq) 10183 { 10184 emlxs_hba_t *hba; 10185 emlxs_port_t *port; 10186 emlxs_buf_t *fpkt; 10187 10188 port = sbp->port; 10189 10190 if (!port) { 10191 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_completion_error_msg, 10192 "NULL port found. sbp=%p flags=%x", sbp, sbp->pkt_flags); 10193 10194 return; 10195 } 10196 10197 hba = HBA; 10198 10199 if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && 10200 (sbp->iotag)) { 10201 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 10202 "WARNING: Completing IO with iotag. sbp=%p iotag=%d " 10203 "xri_flags=%x", 10204 sbp, sbp->iotag, ((sbp->xrip)? sbp->xrip->flag:0)); 10205 10206 emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 10207 } 10208 10209 mutex_enter(&sbp->mtx); 10210 10211 /* Check for error conditions */ 10212 if (sbp->pkt_flags & (PACKET_ULP_OWNED | PACKET_COMPLETED | 10213 PACKET_IN_DONEQ | PACKET_IN_COMPLETION | 10214 PACKET_IN_TXQ | PACKET_IN_CHIPQ)) { 10215 if (sbp->pkt_flags & PACKET_ULP_OWNED) { 10216 EMLXS_MSGF(EMLXS_CONTEXT, 10217 &emlxs_pkt_completion_error_msg, 10218 "Packet already returned. sbp=%p flags=%x", sbp, 10219 sbp->pkt_flags); 10220 } 10221 10222 else if (sbp->pkt_flags & PACKET_COMPLETED) { 10223 EMLXS_MSGF(EMLXS_CONTEXT, 10224 &emlxs_pkt_completion_error_msg, 10225 "Packet already completed. sbp=%p flags=%x", sbp, 10226 sbp->pkt_flags); 10227 } 10228 10229 else if (sbp->pkt_flags & PACKET_IN_DONEQ) { 10230 EMLXS_MSGF(EMLXS_CONTEXT, 10231 &emlxs_pkt_completion_error_msg, 10232 "Pkt already on done queue. sbp=%p flags=%x", sbp, 10233 sbp->pkt_flags); 10234 } 10235 10236 else if (sbp->pkt_flags & PACKET_IN_COMPLETION) { 10237 EMLXS_MSGF(EMLXS_CONTEXT, 10238 &emlxs_pkt_completion_error_msg, 10239 "Packet already in completion. sbp=%p flags=%x", 10240 sbp, sbp->pkt_flags); 10241 } 10242 10243 else if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 10244 EMLXS_MSGF(EMLXS_CONTEXT, 10245 &emlxs_pkt_completion_error_msg, 10246 "Packet still on chip queue. sbp=%p flags=%x", 10247 sbp, sbp->pkt_flags); 10248 } 10249 10250 else if (sbp->pkt_flags & PACKET_IN_TXQ) { 10251 EMLXS_MSGF(EMLXS_CONTEXT, 10252 &emlxs_pkt_completion_error_msg, 10253 "Packet still on tx queue. sbp=%p flags=%x", sbp, 10254 sbp->pkt_flags); 10255 } 10256 10257 mutex_exit(&sbp->mtx); 10258 return; 10259 } 10260 10261 /* Packet is now in completion */ 10262 sbp->pkt_flags |= PACKET_IN_COMPLETION; 10263 10264 /* Set the state if not already set */ 10265 if (!(sbp->pkt_flags & PACKET_STATE_VALID)) { 10266 emlxs_set_pkt_state(sbp, iostat, localstat, 0); 10267 } 10268 10269 /* Check for parent flush packet */ 10270 /* If pkt has a parent flush packet then adjust its count now */ 10271 fpkt = sbp->fpkt; 10272 if (fpkt) { 10273 /* 10274 * We will try to NULL sbp->fpkt inside the 10275 * fpkt's mutex if possible 10276 */ 10277 10278 if (!(fpkt->pkt_flags & PACKET_ULP_OWNED)) { 10279 mutex_enter(&fpkt->mtx); 10280 if (fpkt->flush_count) { 10281 fpkt->flush_count--; 10282 } 10283 sbp->fpkt = NULL; 10284 mutex_exit(&fpkt->mtx); 10285 } else { /* fpkt has been returned already */ 10286 10287 sbp->fpkt = NULL; 10288 } 10289 } 10290 10291 /* If pkt is polled, then wake up sleeping thread */ 10292 if (sbp->pkt_flags & PACKET_POLLED) { 10293 /* Don't set the PACKET_ULP_OWNED flag here */ 10294 /* because the polling thread will do it */ 10295 sbp->pkt_flags |= PACKET_COMPLETED; 10296 mutex_exit(&sbp->mtx); 10297 10298 /* Wake up sleeping thread */ 10299 mutex_enter(&EMLXS_PKT_LOCK); 10300 cv_broadcast(&EMLXS_PKT_CV); 10301 mutex_exit(&EMLXS_PKT_LOCK); 10302 } 10303 10304 /* If packet was generated by our driver, */ 10305 /* then complete it immediately */ 10306 else if (sbp->pkt_flags & PACKET_ALLOCATED) { 10307 mutex_exit(&sbp->mtx); 10308 10309 emlxs_iodone(sbp); 10310 } 10311 10312 /* Put the pkt on the done queue for callback */ 10313 /* completion in another thread */ 10314 else { 10315 sbp->pkt_flags |= PACKET_IN_DONEQ; 10316 sbp->next = NULL; 10317 mutex_exit(&sbp->mtx); 10318 10319 /* Put pkt on doneq, so I/O's will be completed in order */ 10320 mutex_enter(&EMLXS_PORT_LOCK); 10321 if (hba->iodone_tail == NULL) { 10322 hba->iodone_list = sbp; 10323 hba->iodone_count = 1; 10324 } else { 10325 hba->iodone_tail->next = sbp; 10326 hba->iodone_count++; 10327 } 10328 hba->iodone_tail = sbp; 10329 mutex_exit(&EMLXS_PORT_LOCK); 10330 10331 /* Trigger a thread to service the doneq */ 10332 emlxs_thread_trigger1(&hba->iodone_thread, 10333 emlxs_iodone_server); 10334 } 10335 10336 return; 10337 10338 } /* emlxs_pkt_complete() */ 10339 10340 10341 #ifdef SAN_DIAG_SUPPORT 10342 /* 10343 * This routine is called with EMLXS_PORT_LOCK held so we can just increment 10344 * normally. Don't have to use atomic operations. 10345 */ 10346 extern void 10347 emlxs_update_sd_bucket(emlxs_buf_t *sbp) 10348 { 10349 emlxs_port_t *vport; 10350 fc_packet_t *pkt; 10351 uint32_t did; 10352 hrtime_t t; 10353 hrtime_t delta_time; 10354 int i; 10355 NODELIST *ndlp; 10356 10357 vport = sbp->port; 10358 10359 if ((emlxs_sd_bucket.search_type == 0) || 10360 (vport->sd_io_latency_state != SD_COLLECTING)) { 10361 return; 10362 } 10363 10364 /* Compute the iolatency time in microseconds */ 10365 t = gethrtime(); 10366 delta_time = t - sbp->sd_start_time; 10367 pkt = PRIV2PKT(sbp); 10368 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 10369 ndlp = emlxs_node_find_did(vport, did, 1); 10370 10371 if (!ndlp) { 10372 return; 10373 } 10374 10375 if (delta_time >= 10376 emlxs_sd_bucket.values[SD_IO_LATENCY_MAX_BUCKETS - 1]) { 10377 ndlp->sd_dev_bucket[SD_IO_LATENCY_MAX_BUCKETS - 1]. 10378 count++; 10379 } else if (delta_time <= emlxs_sd_bucket.values[0]) { 10380 ndlp->sd_dev_bucket[0].count++; 10381 } else { 10382 for (i = 1; i < SD_IO_LATENCY_MAX_BUCKETS; i++) { 10383 if ((delta_time > emlxs_sd_bucket.values[i-1]) && 10384 (delta_time <= emlxs_sd_bucket.values[i])) { 10385 ndlp->sd_dev_bucket[i].count++; 10386 break; 10387 } 10388 } 10389 } 10390 10391 return; 10392 10393 } /* emlxs_update_sd_bucket() */ 10394 #endif /* SAN_DIAG_SUPPORT */ 10395 10396 /*ARGSUSED*/ 10397 static void 10398 emlxs_iodone_server(void *arg1, void *arg2, void *arg3) 10399 { 10400 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 10401 emlxs_buf_t *sbp; 10402 10403 mutex_enter(&EMLXS_PORT_LOCK); 10404 10405 /* Remove one pkt from the doneq head and complete it */ 10406 while ((sbp = hba->iodone_list) != NULL) { 10407 if ((hba->iodone_list = sbp->next) == NULL) { 10408 hba->iodone_tail = NULL; 10409 hba->iodone_count = 0; 10410 } else { 10411 hba->iodone_count--; 10412 } 10413 10414 mutex_exit(&EMLXS_PORT_LOCK); 10415 10416 /* Prepare the pkt for completion */ 10417 mutex_enter(&sbp->mtx); 10418 sbp->next = NULL; 10419 sbp->pkt_flags &= ~PACKET_IN_DONEQ; 10420 mutex_exit(&sbp->mtx); 10421 10422 /* Complete the IO now */ 10423 emlxs_iodone(sbp); 10424 10425 /* Reacquire lock and check if more work is to be done */ 10426 mutex_enter(&EMLXS_PORT_LOCK); 10427 } 10428 10429 mutex_exit(&EMLXS_PORT_LOCK); 10430 10431 #ifdef FMA_SUPPORT 10432 if (hba->flag & FC_DMA_CHECK_ERROR) { 10433 emlxs_thread_spawn(hba, emlxs_restart_thread, 10434 NULL, NULL); 10435 } 10436 #endif /* FMA_SUPPORT */ 10437 10438 return; 10439 10440 } /* End emlxs_iodone_server */ 10441 10442 10443 static void 10444 emlxs_iodone(emlxs_buf_t *sbp) 10445 { 10446 #ifdef FMA_SUPPORT 10447 emlxs_port_t *port = sbp->port; 10448 emlxs_hba_t *hba = port->hba; 10449 #endif /* FMA_SUPPORT */ 10450 10451 fc_packet_t *pkt; 10452 CHANNEL *cp; 10453 10454 pkt = PRIV2PKT(sbp); 10455 10456 /* Check one more time that the pkt has not already been returned */ 10457 if (sbp->pkt_flags & PACKET_ULP_OWNED) { 10458 return; 10459 } 10460 10461 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 10462 emlxs_unswap_pkt(sbp); 10463 #endif /* EMLXS_MODREV2X */ 10464 10465 mutex_enter(&sbp->mtx); 10466 sbp->pkt_flags |= (PACKET_COMPLETED | PACKET_ULP_OWNED); 10467 mutex_exit(&sbp->mtx); 10468 10469 if (pkt->pkt_comp) { 10470 #ifdef FMA_SUPPORT 10471 emlxs_check_dma(hba, sbp); 10472 #endif /* FMA_SUPPORT */ 10473 10474 if (sbp->channel) { 10475 cp = (CHANNEL *)sbp->channel; 10476 cp->ulpCmplCmd++; 10477 } 10478 10479 (*pkt->pkt_comp) (pkt); 10480 } 10481 10482 return; 10483 10484 } /* emlxs_iodone() */ 10485 10486 10487 10488 extern fc_unsol_buf_t * 10489 emlxs_ub_find(emlxs_port_t *port, uint32_t token) 10490 { 10491 emlxs_unsol_buf_t *pool; 10492 fc_unsol_buf_t *ubp; 10493 emlxs_ub_priv_t *ub_priv; 10494 10495 /* Check if this is a valid ub token */ 10496 if (token < EMLXS_UB_TOKEN_OFFSET) { 10497 return (NULL); 10498 } 10499 10500 mutex_enter(&EMLXS_UB_LOCK); 10501 10502 pool = port->ub_pool; 10503 while (pool) { 10504 /* Find a pool with the proper token range */ 10505 if (token >= pool->pool_first_token && 10506 token <= pool->pool_last_token) { 10507 ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[(token - 10508 pool->pool_first_token)]; 10509 ub_priv = ubp->ub_fca_private; 10510 10511 if (ub_priv->token != token) { 10512 EMLXS_MSGF(EMLXS_CONTEXT, 10513 &emlxs_sfs_debug_msg, 10514 "ub_find: Invalid token=%x", ubp, token, 10515 ub_priv->token); 10516 10517 ubp = NULL; 10518 } 10519 10520 else if (!(ub_priv->flags & EMLXS_UB_IN_USE)) { 10521 EMLXS_MSGF(EMLXS_CONTEXT, 10522 &emlxs_sfs_debug_msg, 10523 "ub_find: Buffer not in use. buffer=%p " 10524 "token=%x", ubp, token); 10525 10526 ubp = NULL; 10527 } 10528 10529 mutex_exit(&EMLXS_UB_LOCK); 10530 10531 return (ubp); 10532 } 10533 10534 pool = pool->pool_next; 10535 } 10536 10537 mutex_exit(&EMLXS_UB_LOCK); 10538 10539 return (NULL); 10540 10541 } /* emlxs_ub_find() */ 10542 10543 10544 10545 extern fc_unsol_buf_t * 10546 emlxs_ub_get(emlxs_port_t *port, uint32_t size, uint32_t type, 10547 uint32_t reserve) 10548 { 10549 emlxs_hba_t *hba = HBA; 10550 emlxs_unsol_buf_t *pool; 10551 fc_unsol_buf_t *ubp; 10552 emlxs_ub_priv_t *ub_priv; 10553 uint32_t i; 10554 uint32_t resv_flag; 10555 uint32_t pool_free; 10556 uint32_t pool_free_resv; 10557 10558 mutex_enter(&EMLXS_UB_LOCK); 10559 10560 pool = port->ub_pool; 10561 while (pool) { 10562 /* Find a pool of the appropriate type and size */ 10563 if ((pool->pool_available == 0) || 10564 (pool->pool_type != type) || 10565 (pool->pool_buf_size < size)) { 10566 goto next_pool; 10567 } 10568 10569 10570 /* Adjust free counts based on availablity */ 10571 /* The free reserve count gets first priority */ 10572 pool_free_resv = 10573 min(pool->pool_free_resv, pool->pool_available); 10574 pool_free = 10575 min(pool->pool_free, 10576 (pool->pool_available - pool_free_resv)); 10577 10578 /* Initialize reserve flag */ 10579 resv_flag = reserve; 10580 10581 if (resv_flag) { 10582 if (pool_free_resv == 0) { 10583 if (pool_free == 0) { 10584 goto next_pool; 10585 } 10586 resv_flag = 0; 10587 } 10588 } else if (pool_free == 0) { 10589 goto next_pool; 10590 } 10591 10592 /* Find next available free buffer in this pool */ 10593 for (i = 0; i < pool->pool_nentries; i++) { 10594 ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[i]; 10595 ub_priv = ubp->ub_fca_private; 10596 10597 if (!ub_priv->available || 10598 ub_priv->flags != EMLXS_UB_FREE) { 10599 continue; 10600 } 10601 10602 ub_priv->time = hba->timer_tics; 10603 10604 /* Timeout in 5 minutes */ 10605 ub_priv->timeout = (5 * 60); 10606 10607 ub_priv->flags = EMLXS_UB_IN_USE; 10608 10609 /* Alloc the buffer from the pool */ 10610 if (resv_flag) { 10611 ub_priv->flags |= EMLXS_UB_RESV; 10612 pool->pool_free_resv--; 10613 } else { 10614 pool->pool_free--; 10615 } 10616 10617 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, 10618 "ub_get: ubp=%p token=%x (%d,%d,%d,%d)", ubp, 10619 ub_priv->token, pool->pool_nentries, 10620 pool->pool_available, pool->pool_free, 10621 pool->pool_free_resv); 10622 10623 mutex_exit(&EMLXS_UB_LOCK); 10624 10625 return (ubp); 10626 } 10627 next_pool: 10628 10629 pool = pool->pool_next; 10630 } 10631 10632 mutex_exit(&EMLXS_UB_LOCK); 10633 10634 return (NULL); 10635 10636 } /* emlxs_ub_get() */ 10637 10638 10639 10640 extern void 10641 emlxs_set_pkt_state(emlxs_buf_t *sbp, uint32_t iostat, uint8_t localstat, 10642 uint32_t lock) 10643 { 10644 fc_packet_t *pkt; 10645 fcp_rsp_t *fcp_rsp; 10646 uint32_t i; 10647 emlxs_xlat_err_t *tptr; 10648 emlxs_xlat_err_t *entry; 10649 10650 10651 pkt = PRIV2PKT(sbp); 10652 10653 /* Warning: Some FCT sbp's don't have */ 10654 /* fc_packet objects, so just return */ 10655 if (!pkt) { 10656 return; 10657 } 10658 10659 if (lock) { 10660 mutex_enter(&sbp->mtx); 10661 } 10662 10663 if (!(sbp->pkt_flags & PACKET_STATE_VALID)) { 10664 sbp->pkt_flags |= PACKET_STATE_VALID; 10665 10666 /* Perform table lookup */ 10667 entry = NULL; 10668 if (iostat != IOSTAT_LOCAL_REJECT) { 10669 tptr = emlxs_iostat_tbl; 10670 for (i = 0; i < IOSTAT_MAX; i++, tptr++) { 10671 if (iostat == tptr->emlxs_status) { 10672 entry = tptr; 10673 break; 10674 } 10675 } 10676 } else { /* iostate == IOSTAT_LOCAL_REJECT */ 10677 10678 tptr = emlxs_ioerr_tbl; 10679 for (i = 0; i < IOERR_MAX; i++, tptr++) { 10680 if (localstat == tptr->emlxs_status) { 10681 entry = tptr; 10682 break; 10683 } 10684 } 10685 } 10686 10687 if (entry) { 10688 pkt->pkt_state = entry->pkt_state; 10689 pkt->pkt_reason = entry->pkt_reason; 10690 pkt->pkt_expln = entry->pkt_expln; 10691 pkt->pkt_action = entry->pkt_action; 10692 } else { 10693 /* Set defaults */ 10694 pkt->pkt_state = FC_PKT_TRAN_ERROR; 10695 pkt->pkt_reason = FC_REASON_ABORTED; 10696 pkt->pkt_expln = FC_EXPLN_NONE; 10697 pkt->pkt_action = FC_ACTION_RETRYABLE; 10698 } 10699 10700 10701 /* Set the residual counts and response frame */ 10702 /* Check if response frame was received from the chip */ 10703 /* If so, then the residual counts will already be set */ 10704 if (!(sbp->pkt_flags & (PACKET_FCP_RSP_VALID | 10705 PACKET_CT_RSP_VALID | PACKET_ELS_RSP_VALID))) { 10706 /* We have to create the response frame */ 10707 if (iostat == IOSTAT_SUCCESS) { 10708 pkt->pkt_resp_resid = 0; 10709 pkt->pkt_data_resid = 0; 10710 10711 if ((pkt->pkt_cmd_fhdr.type == 10712 FC_TYPE_SCSI_FCP) && pkt->pkt_rsplen && 10713 pkt->pkt_resp) { 10714 fcp_rsp = (fcp_rsp_t *)pkt->pkt_resp; 10715 10716 fcp_rsp->fcp_u.fcp_status. 10717 rsp_len_set = 1; 10718 fcp_rsp->fcp_response_len = 8; 10719 } 10720 } else { 10721 /* Otherwise assume no data */ 10722 /* and no response received */ 10723 pkt->pkt_data_resid = pkt->pkt_datalen; 10724 pkt->pkt_resp_resid = pkt->pkt_rsplen; 10725 } 10726 } 10727 } 10728 10729 if (lock) { 10730 mutex_exit(&sbp->mtx); 10731 } 10732 10733 return; 10734 10735 } /* emlxs_set_pkt_state() */ 10736 10737 10738 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 10739 10740 extern void 10741 emlxs_swap_service_params(SERV_PARM *sp) 10742 { 10743 uint16_t *p; 10744 int size; 10745 int i; 10746 10747 size = (sizeof (CSP) - 4) / 2; 10748 p = (uint16_t *)&sp->cmn; 10749 for (i = 0; i < size; i++) { 10750 p[i] = LE_SWAP16(p[i]); 10751 } 10752 sp->cmn.e_d_tov = LE_SWAP32(sp->cmn.e_d_tov); 10753 10754 size = sizeof (CLASS_PARMS) / 2; 10755 p = (uint16_t *)&sp->cls1; 10756 for (i = 0; i < size; i++, p++) { 10757 *p = LE_SWAP16(*p); 10758 } 10759 10760 size = sizeof (CLASS_PARMS) / 2; 10761 p = (uint16_t *)&sp->cls2; 10762 for (i = 0; i < size; i++, p++) { 10763 *p = LE_SWAP16(*p); 10764 } 10765 10766 size = sizeof (CLASS_PARMS) / 2; 10767 p = (uint16_t *)&sp->cls3; 10768 for (i = 0; i < size; i++, p++) { 10769 *p = LE_SWAP16(*p); 10770 } 10771 10772 size = sizeof (CLASS_PARMS) / 2; 10773 p = (uint16_t *)&sp->cls4; 10774 for (i = 0; i < size; i++, p++) { 10775 *p = LE_SWAP16(*p); 10776 } 10777 10778 return; 10779 10780 } /* emlxs_swap_service_params() */ 10781 10782 extern void 10783 emlxs_unswap_pkt(emlxs_buf_t *sbp) 10784 { 10785 if (sbp->pkt_flags & PACKET_FCP_SWAPPED) { 10786 emlxs_swap_fcp_pkt(sbp); 10787 } 10788 10789 else if (sbp->pkt_flags & PACKET_ELS_SWAPPED) { 10790 emlxs_swap_els_pkt(sbp); 10791 } 10792 10793 else if (sbp->pkt_flags & PACKET_CT_SWAPPED) { 10794 emlxs_swap_ct_pkt(sbp); 10795 } 10796 10797 } /* emlxs_unswap_pkt() */ 10798 10799 10800 extern void 10801 emlxs_swap_fcp_pkt(emlxs_buf_t *sbp) 10802 { 10803 fc_packet_t *pkt; 10804 FCP_CMND *cmd; 10805 fcp_rsp_t *rsp; 10806 uint16_t *lunp; 10807 uint32_t i; 10808 10809 mutex_enter(&sbp->mtx); 10810 10811 if (sbp->pkt_flags & PACKET_ALLOCATED) { 10812 mutex_exit(&sbp->mtx); 10813 return; 10814 } 10815 10816 if (sbp->pkt_flags & PACKET_FCP_SWAPPED) { 10817 sbp->pkt_flags &= ~PACKET_FCP_SWAPPED; 10818 } else { 10819 sbp->pkt_flags |= PACKET_FCP_SWAPPED; 10820 } 10821 10822 mutex_exit(&sbp->mtx); 10823 10824 pkt = PRIV2PKT(sbp); 10825 10826 cmd = (FCP_CMND *)pkt->pkt_cmd; 10827 rsp = (pkt->pkt_rsplen && 10828 (sbp->pkt_flags & PACKET_FCP_RSP_VALID)) ? 10829 (fcp_rsp_t *)pkt->pkt_resp : NULL; 10830 10831 /* The size of data buffer needs to be swapped. */ 10832 cmd->fcpDl = LE_SWAP32(cmd->fcpDl); 10833 10834 /* 10835 * Swap first 2 words of FCP CMND payload. 10836 */ 10837 lunp = (uint16_t *)&cmd->fcpLunMsl; 10838 for (i = 0; i < 4; i++) { 10839 lunp[i] = LE_SWAP16(lunp[i]); 10840 } 10841 10842 if (rsp) { 10843 rsp->fcp_resid = LE_SWAP32(rsp->fcp_resid); 10844 rsp->fcp_sense_len = LE_SWAP32(rsp->fcp_sense_len); 10845 rsp->fcp_response_len = LE_SWAP32(rsp->fcp_response_len); 10846 } 10847 10848 return; 10849 10850 } /* emlxs_swap_fcp_pkt() */ 10851 10852 10853 extern void 10854 emlxs_swap_els_pkt(emlxs_buf_t *sbp) 10855 { 10856 fc_packet_t *pkt; 10857 uint32_t *cmd; 10858 uint32_t *rsp; 10859 uint32_t command; 10860 uint16_t *c; 10861 uint32_t i; 10862 uint32_t swapped; 10863 10864 mutex_enter(&sbp->mtx); 10865 10866 if (sbp->pkt_flags & PACKET_ALLOCATED) { 10867 mutex_exit(&sbp->mtx); 10868 return; 10869 } 10870 10871 if (sbp->pkt_flags & PACKET_ELS_SWAPPED) { 10872 sbp->pkt_flags &= ~PACKET_ELS_SWAPPED; 10873 swapped = 1; 10874 } else { 10875 sbp->pkt_flags |= PACKET_ELS_SWAPPED; 10876 swapped = 0; 10877 } 10878 10879 mutex_exit(&sbp->mtx); 10880 10881 pkt = PRIV2PKT(sbp); 10882 10883 cmd = (uint32_t *)pkt->pkt_cmd; 10884 rsp = (pkt->pkt_rsplen && 10885 (sbp->pkt_flags & PACKET_ELS_RSP_VALID)) ? 10886 (uint32_t *)pkt->pkt_resp : NULL; 10887 10888 if (!swapped) { 10889 cmd[0] = LE_SWAP32(cmd[0]); 10890 command = cmd[0] & ELS_CMD_MASK; 10891 } else { 10892 command = cmd[0] & ELS_CMD_MASK; 10893 cmd[0] = LE_SWAP32(cmd[0]); 10894 } 10895 10896 if (rsp) { 10897 rsp[0] = LE_SWAP32(rsp[0]); 10898 } 10899 10900 switch (command) { 10901 case ELS_CMD_ACC: 10902 if (sbp->ucmd == ELS_CMD_ADISC) { 10903 /* Hard address of originator */ 10904 cmd[1] = LE_SWAP32(cmd[1]); 10905 10906 /* N_Port ID of originator */ 10907 cmd[6] = LE_SWAP32(cmd[6]); 10908 } 10909 break; 10910 10911 case ELS_CMD_PLOGI: 10912 case ELS_CMD_FLOGI: 10913 case ELS_CMD_FDISC: 10914 if (rsp) { 10915 emlxs_swap_service_params((SERV_PARM *) & rsp[1]); 10916 } 10917 break; 10918 10919 case ELS_CMD_LOGO: 10920 cmd[1] = LE_SWAP32(cmd[1]); /* N_Port ID */ 10921 break; 10922 10923 case ELS_CMD_RLS: 10924 cmd[1] = LE_SWAP32(cmd[1]); 10925 10926 if (rsp) { 10927 for (i = 0; i < 6; i++) { 10928 rsp[1 + i] = LE_SWAP32(rsp[1 + i]); 10929 } 10930 } 10931 break; 10932 10933 case ELS_CMD_ADISC: 10934 cmd[1] = LE_SWAP32(cmd[1]); /* Hard address of originator */ 10935 cmd[6] = LE_SWAP32(cmd[6]); /* N_Port ID of originator */ 10936 break; 10937 10938 case ELS_CMD_PRLI: 10939 c = (uint16_t *)&cmd[1]; 10940 c[1] = LE_SWAP16(c[1]); 10941 10942 cmd[4] = LE_SWAP32(cmd[4]); 10943 10944 if (rsp) { 10945 rsp[4] = LE_SWAP32(rsp[4]); 10946 } 10947 break; 10948 10949 case ELS_CMD_SCR: 10950 cmd[1] = LE_SWAP32(cmd[1]); 10951 break; 10952 10953 case ELS_CMD_LINIT: 10954 if (rsp) { 10955 rsp[1] = LE_SWAP32(rsp[1]); 10956 } 10957 break; 10958 10959 default: 10960 break; 10961 } 10962 10963 return; 10964 10965 } /* emlxs_swap_els_pkt() */ 10966 10967 10968 extern void 10969 emlxs_swap_ct_pkt(emlxs_buf_t *sbp) 10970 { 10971 fc_packet_t *pkt; 10972 uint32_t *cmd; 10973 uint32_t *rsp; 10974 uint32_t command; 10975 uint32_t i; 10976 uint32_t swapped; 10977 10978 mutex_enter(&sbp->mtx); 10979 10980 if (sbp->pkt_flags & PACKET_ALLOCATED) { 10981 mutex_exit(&sbp->mtx); 10982 return; 10983 } 10984 10985 if (sbp->pkt_flags & PACKET_CT_SWAPPED) { 10986 sbp->pkt_flags &= ~PACKET_CT_SWAPPED; 10987 swapped = 1; 10988 } else { 10989 sbp->pkt_flags |= PACKET_CT_SWAPPED; 10990 swapped = 0; 10991 } 10992 10993 mutex_exit(&sbp->mtx); 10994 10995 pkt = PRIV2PKT(sbp); 10996 10997 cmd = (uint32_t *)pkt->pkt_cmd; 10998 rsp = (pkt->pkt_rsplen && 10999 (sbp->pkt_flags & PACKET_CT_RSP_VALID)) ? 11000 (uint32_t *)pkt->pkt_resp : NULL; 11001 11002 if (!swapped) { 11003 cmd[0] = 0x01000000; 11004 command = cmd[2]; 11005 } 11006 11007 cmd[0] = LE_SWAP32(cmd[0]); 11008 cmd[1] = LE_SWAP32(cmd[1]); 11009 cmd[2] = LE_SWAP32(cmd[2]); 11010 cmd[3] = LE_SWAP32(cmd[3]); 11011 11012 if (swapped) { 11013 command = cmd[2]; 11014 } 11015 11016 switch ((command >> 16)) { 11017 case SLI_CTNS_GA_NXT: 11018 cmd[4] = LE_SWAP32(cmd[4]); 11019 break; 11020 11021 case SLI_CTNS_GPN_ID: 11022 case SLI_CTNS_GNN_ID: 11023 case SLI_CTNS_RPN_ID: 11024 case SLI_CTNS_RNN_ID: 11025 case SLI_CTNS_RSPN_ID: 11026 cmd[4] = LE_SWAP32(cmd[4]); 11027 break; 11028 11029 case SLI_CTNS_RCS_ID: 11030 case SLI_CTNS_RPT_ID: 11031 cmd[4] = LE_SWAP32(cmd[4]); 11032 cmd[5] = LE_SWAP32(cmd[5]); 11033 break; 11034 11035 case SLI_CTNS_RFT_ID: 11036 cmd[4] = LE_SWAP32(cmd[4]); 11037 11038 /* Swap FC4 types */ 11039 for (i = 0; i < 8; i++) { 11040 cmd[5 + i] = LE_SWAP32(cmd[5 + i]); 11041 } 11042 break; 11043 11044 case SLI_CTNS_GFT_ID: 11045 if (rsp) { 11046 /* Swap FC4 types */ 11047 for (i = 0; i < 8; i++) { 11048 rsp[4 + i] = LE_SWAP32(rsp[4 + i]); 11049 } 11050 } 11051 break; 11052 11053 case SLI_CTNS_GCS_ID: 11054 case SLI_CTNS_GSPN_ID: 11055 case SLI_CTNS_GSNN_NN: 11056 case SLI_CTNS_GIP_NN: 11057 case SLI_CTNS_GIPA_NN: 11058 11059 case SLI_CTNS_GPT_ID: 11060 case SLI_CTNS_GID_NN: 11061 case SLI_CTNS_GNN_IP: 11062 case SLI_CTNS_GIPA_IP: 11063 case SLI_CTNS_GID_FT: 11064 case SLI_CTNS_GID_PT: 11065 case SLI_CTNS_GID_PN: 11066 case SLI_CTNS_RIP_NN: 11067 case SLI_CTNS_RIPA_NN: 11068 case SLI_CTNS_RSNN_NN: 11069 case SLI_CTNS_DA_ID: 11070 case SLI_CT_RESPONSE_FS_RJT: 11071 case SLI_CT_RESPONSE_FS_ACC: 11072 11073 default: 11074 break; 11075 } 11076 return; 11077 11078 } /* emlxs_swap_ct_pkt() */ 11079 11080 11081 extern void 11082 emlxs_swap_els_ub(fc_unsol_buf_t *ubp) 11083 { 11084 emlxs_ub_priv_t *ub_priv; 11085 fc_rscn_t *rscn; 11086 uint32_t count; 11087 uint32_t i; 11088 uint32_t *lp; 11089 la_els_logi_t *logi; 11090 11091 ub_priv = ubp->ub_fca_private; 11092 11093 switch (ub_priv->cmd) { 11094 case ELS_CMD_RSCN: 11095 rscn = (fc_rscn_t *)ubp->ub_buffer; 11096 11097 rscn->rscn_payload_len = LE_SWAP16(rscn->rscn_payload_len); 11098 11099 count = ((rscn->rscn_payload_len - 4) / 4); 11100 lp = (uint32_t *)ubp->ub_buffer + 1; 11101 for (i = 0; i < count; i++, lp++) { 11102 *lp = LE_SWAP32(*lp); 11103 } 11104 11105 break; 11106 11107 case ELS_CMD_FLOGI: 11108 case ELS_CMD_PLOGI: 11109 case ELS_CMD_FDISC: 11110 case ELS_CMD_PDISC: 11111 logi = (la_els_logi_t *)ubp->ub_buffer; 11112 emlxs_swap_service_params( 11113 (SERV_PARM *)&logi->common_service); 11114 break; 11115 11116 /* ULP handles this */ 11117 case ELS_CMD_LOGO: 11118 case ELS_CMD_PRLI: 11119 case ELS_CMD_PRLO: 11120 case ELS_CMD_ADISC: 11121 default: 11122 break; 11123 } 11124 11125 return; 11126 11127 } /* emlxs_swap_els_ub() */ 11128 11129 11130 #endif /* EMLXS_MODREV2X */ 11131 11132 11133 extern char * 11134 emlxs_mode_xlate(uint32_t mode) 11135 { 11136 static char buffer[32]; 11137 uint32_t i; 11138 uint32_t count; 11139 11140 count = sizeof (emlxs_mode_table) / sizeof (emlxs_table_t); 11141 for (i = 0; i < count; i++) { 11142 if (mode == emlxs_mode_table[i].code) { 11143 return (emlxs_mode_table[i].string); 11144 } 11145 } 11146 11147 (void) snprintf(buffer, sizeof (buffer), "Unknown (%x)", mode); 11148 return (buffer); 11149 11150 } /* emlxs_mode_xlate() */ 11151 11152 11153 extern char * 11154 emlxs_elscmd_xlate(uint32_t elscmd) 11155 { 11156 static char buffer[32]; 11157 uint32_t i; 11158 uint32_t count; 11159 11160 count = sizeof (emlxs_elscmd_table) / sizeof (emlxs_table_t); 11161 for (i = 0; i < count; i++) { 11162 if (elscmd == emlxs_elscmd_table[i].code) { 11163 return (emlxs_elscmd_table[i].string); 11164 } 11165 } 11166 11167 (void) snprintf(buffer, sizeof (buffer), "ELS=0x%x", elscmd); 11168 return (buffer); 11169 11170 } /* emlxs_elscmd_xlate() */ 11171 11172 11173 extern char * 11174 emlxs_ctcmd_xlate(uint32_t ctcmd) 11175 { 11176 static char buffer[32]; 11177 uint32_t i; 11178 uint32_t count; 11179 11180 count = sizeof (emlxs_ctcmd_table) / sizeof (emlxs_table_t); 11181 for (i = 0; i < count; i++) { 11182 if (ctcmd == emlxs_ctcmd_table[i].code) { 11183 return (emlxs_ctcmd_table[i].string); 11184 } 11185 } 11186 11187 (void) snprintf(buffer, sizeof (buffer), "cmd=0x%x", ctcmd); 11188 return (buffer); 11189 11190 } /* emlxs_ctcmd_xlate() */ 11191 11192 11193 #ifdef MENLO_SUPPORT 11194 extern char * 11195 emlxs_menlo_cmd_xlate(uint32_t cmd) 11196 { 11197 static char buffer[32]; 11198 uint32_t i; 11199 uint32_t count; 11200 11201 count = sizeof (emlxs_menlo_cmd_table) / sizeof (emlxs_table_t); 11202 for (i = 0; i < count; i++) { 11203 if (cmd == emlxs_menlo_cmd_table[i].code) { 11204 return (emlxs_menlo_cmd_table[i].string); 11205 } 11206 } 11207 11208 (void) snprintf(buffer, sizeof (buffer), "Cmd=0x%x", cmd); 11209 return (buffer); 11210 11211 } /* emlxs_menlo_cmd_xlate() */ 11212 11213 extern char * 11214 emlxs_menlo_rsp_xlate(uint32_t rsp) 11215 { 11216 static char buffer[32]; 11217 uint32_t i; 11218 uint32_t count; 11219 11220 count = sizeof (emlxs_menlo_rsp_table) / sizeof (emlxs_table_t); 11221 for (i = 0; i < count; i++) { 11222 if (rsp == emlxs_menlo_rsp_table[i].code) { 11223 return (emlxs_menlo_rsp_table[i].string); 11224 } 11225 } 11226 11227 (void) snprintf(buffer, sizeof (buffer), "Rsp=0x%x", rsp); 11228 return (buffer); 11229 11230 } /* emlxs_menlo_rsp_xlate() */ 11231 11232 #endif /* MENLO_SUPPORT */ 11233 11234 11235 extern char * 11236 emlxs_rmcmd_xlate(uint32_t rmcmd) 11237 { 11238 static char buffer[32]; 11239 uint32_t i; 11240 uint32_t count; 11241 11242 count = sizeof (emlxs_rmcmd_table) / sizeof (emlxs_table_t); 11243 for (i = 0; i < count; i++) { 11244 if (rmcmd == emlxs_rmcmd_table[i].code) { 11245 return (emlxs_rmcmd_table[i].string); 11246 } 11247 } 11248 11249 (void) snprintf(buffer, sizeof (buffer), "RM=0x%x", rmcmd); 11250 return (buffer); 11251 11252 } /* emlxs_rmcmd_xlate() */ 11253 11254 11255 11256 extern char * 11257 emlxs_mscmd_xlate(uint16_t mscmd) 11258 { 11259 static char buffer[32]; 11260 uint32_t i; 11261 uint32_t count; 11262 11263 count = sizeof (emlxs_mscmd_table) / sizeof (emlxs_table_t); 11264 for (i = 0; i < count; i++) { 11265 if (mscmd == emlxs_mscmd_table[i].code) { 11266 return (emlxs_mscmd_table[i].string); 11267 } 11268 } 11269 11270 (void) snprintf(buffer, sizeof (buffer), "Cmd=0x%x", mscmd); 11271 return (buffer); 11272 11273 } /* emlxs_mscmd_xlate() */ 11274 11275 11276 extern char * 11277 emlxs_state_xlate(uint8_t state) 11278 { 11279 static char buffer[32]; 11280 uint32_t i; 11281 uint32_t count; 11282 11283 count = sizeof (emlxs_state_table) / sizeof (emlxs_table_t); 11284 for (i = 0; i < count; i++) { 11285 if (state == emlxs_state_table[i].code) { 11286 return (emlxs_state_table[i].string); 11287 } 11288 } 11289 11290 (void) snprintf(buffer, sizeof (buffer), "State=0x%x", state); 11291 return (buffer); 11292 11293 } /* emlxs_state_xlate() */ 11294 11295 11296 extern char * 11297 emlxs_error_xlate(uint8_t errno) 11298 { 11299 static char buffer[32]; 11300 uint32_t i; 11301 uint32_t count; 11302 11303 count = sizeof (emlxs_error_table) / sizeof (emlxs_table_t); 11304 for (i = 0; i < count; i++) { 11305 if (errno == emlxs_error_table[i].code) { 11306 return (emlxs_error_table[i].string); 11307 } 11308 } 11309 11310 (void) snprintf(buffer, sizeof (buffer), "Errno=0x%x", errno); 11311 return (buffer); 11312 11313 } /* emlxs_error_xlate() */ 11314 11315 11316 static int 11317 emlxs_pm_lower_power(dev_info_t *dip) 11318 { 11319 int ddiinst; 11320 int emlxinst; 11321 emlxs_config_t *cfg; 11322 int32_t rval; 11323 emlxs_hba_t *hba; 11324 11325 ddiinst = ddi_get_instance(dip); 11326 emlxinst = emlxs_get_instance(ddiinst); 11327 hba = emlxs_device.hba[emlxinst]; 11328 cfg = &CFG; 11329 11330 rval = DDI_SUCCESS; 11331 11332 /* Lower the power level */ 11333 if (cfg[CFG_PM_SUPPORT].current) { 11334 rval = 11335 pm_lower_power(dip, EMLXS_PM_ADAPTER, 11336 EMLXS_PM_ADAPTER_DOWN); 11337 } else { 11338 /* We do not have kernel support of power management enabled */ 11339 /* therefore, call our power management routine directly */ 11340 rval = 11341 emlxs_power(dip, EMLXS_PM_ADAPTER, EMLXS_PM_ADAPTER_DOWN); 11342 } 11343 11344 return (rval); 11345 11346 } /* emlxs_pm_lower_power() */ 11347 11348 11349 static int 11350 emlxs_pm_raise_power(dev_info_t *dip) 11351 { 11352 int ddiinst; 11353 int emlxinst; 11354 emlxs_config_t *cfg; 11355 int32_t rval; 11356 emlxs_hba_t *hba; 11357 11358 ddiinst = ddi_get_instance(dip); 11359 emlxinst = emlxs_get_instance(ddiinst); 11360 hba = emlxs_device.hba[emlxinst]; 11361 cfg = &CFG; 11362 11363 /* Raise the power level */ 11364 if (cfg[CFG_PM_SUPPORT].current) { 11365 rval = 11366 pm_raise_power(dip, EMLXS_PM_ADAPTER, 11367 EMLXS_PM_ADAPTER_UP); 11368 } else { 11369 /* We do not have kernel support of power management enabled */ 11370 /* therefore, call our power management routine directly */ 11371 rval = 11372 emlxs_power(dip, EMLXS_PM_ADAPTER, EMLXS_PM_ADAPTER_UP); 11373 } 11374 11375 return (rval); 11376 11377 } /* emlxs_pm_raise_power() */ 11378 11379 11380 #ifdef IDLE_TIMER 11381 11382 extern int 11383 emlxs_pm_busy_component(emlxs_hba_t *hba) 11384 { 11385 emlxs_config_t *cfg = &CFG; 11386 int rval; 11387 11388 hba->pm_active = 1; 11389 11390 if (hba->pm_busy) { 11391 return (DDI_SUCCESS); 11392 } 11393 11394 mutex_enter(&EMLXS_PM_LOCK); 11395 11396 if (hba->pm_busy) { 11397 mutex_exit(&EMLXS_PM_LOCK); 11398 return (DDI_SUCCESS); 11399 } 11400 hba->pm_busy = 1; 11401 11402 mutex_exit(&EMLXS_PM_LOCK); 11403 11404 /* Attempt to notify system that we are busy */ 11405 if (cfg[CFG_PM_SUPPORT].current) { 11406 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 11407 "pm_busy_component."); 11408 11409 rval = pm_busy_component(dip, EMLXS_PM_ADAPTER); 11410 11411 if (rval != DDI_SUCCESS) { 11412 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 11413 "pm_busy_component failed. ret=%d", rval); 11414 11415 /* If this attempt failed then clear our flags */ 11416 mutex_enter(&EMLXS_PM_LOCK); 11417 hba->pm_busy = 0; 11418 mutex_exit(&EMLXS_PM_LOCK); 11419 11420 return (rval); 11421 } 11422 } 11423 11424 return (DDI_SUCCESS); 11425 11426 } /* emlxs_pm_busy_component() */ 11427 11428 11429 extern int 11430 emlxs_pm_idle_component(emlxs_hba_t *hba) 11431 { 11432 emlxs_config_t *cfg = &CFG; 11433 int rval; 11434 11435 if (!hba->pm_busy) { 11436 return (DDI_SUCCESS); 11437 } 11438 11439 mutex_enter(&EMLXS_PM_LOCK); 11440 11441 if (!hba->pm_busy) { 11442 mutex_exit(&EMLXS_PM_LOCK); 11443 return (DDI_SUCCESS); 11444 } 11445 hba->pm_busy = 0; 11446 11447 mutex_exit(&EMLXS_PM_LOCK); 11448 11449 if (cfg[CFG_PM_SUPPORT].current) { 11450 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 11451 "pm_idle_component."); 11452 11453 rval = pm_idle_component(dip, EMLXS_PM_ADAPTER); 11454 11455 if (rval != DDI_SUCCESS) { 11456 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 11457 "pm_idle_component failed. ret=%d", rval); 11458 11459 /* If this attempt failed then */ 11460 /* reset our flags for another attempt */ 11461 mutex_enter(&EMLXS_PM_LOCK); 11462 hba->pm_busy = 1; 11463 mutex_exit(&EMLXS_PM_LOCK); 11464 11465 return (rval); 11466 } 11467 } 11468 11469 return (DDI_SUCCESS); 11470 11471 } /* emlxs_pm_idle_component() */ 11472 11473 11474 extern void 11475 emlxs_pm_idle_timer(emlxs_hba_t *hba) 11476 { 11477 emlxs_config_t *cfg = &CFG; 11478 11479 if (hba->pm_active) { 11480 /* Clear active flag and reset idle timer */ 11481 mutex_enter(&EMLXS_PM_LOCK); 11482 hba->pm_active = 0; 11483 hba->pm_idle_timer = 11484 hba->timer_tics + cfg[CFG_PM_IDLE].current; 11485 mutex_exit(&EMLXS_PM_LOCK); 11486 } 11487 11488 /* Check for idle timeout */ 11489 else if (hba->timer_tics >= hba->pm_idle_timer) { 11490 if (emlxs_pm_idle_component(hba) == DDI_SUCCESS) { 11491 mutex_enter(&EMLXS_PM_LOCK); 11492 hba->pm_idle_timer = 11493 hba->timer_tics + cfg[CFG_PM_IDLE].current; 11494 mutex_exit(&EMLXS_PM_LOCK); 11495 } 11496 } 11497 11498 return; 11499 11500 } /* emlxs_pm_idle_timer() */ 11501 11502 #endif /* IDLE_TIMER */ 11503 11504 11505 #if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4) 11506 static void 11507 emlxs_read_vport_prop(emlxs_hba_t *hba) 11508 { 11509 emlxs_port_t *port = &PPORT; 11510 emlxs_config_t *cfg = &CFG; 11511 char **arrayp; 11512 uint8_t *s; 11513 uint8_t *np; 11514 NAME_TYPE pwwpn; 11515 NAME_TYPE wwnn; 11516 NAME_TYPE wwpn; 11517 uint32_t vpi; 11518 uint32_t cnt; 11519 uint32_t rval; 11520 uint32_t i; 11521 uint32_t j; 11522 uint32_t c1; 11523 uint32_t sum; 11524 uint32_t errors; 11525 char buffer[64]; 11526 11527 /* Check for the per adapter vport setting */ 11528 (void) snprintf(buffer, sizeof (buffer), "%s%d-vport", DRIVER_NAME, 11529 hba->ddiinst); 11530 cnt = 0; 11531 arrayp = NULL; 11532 rval = 11533 ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip, 11534 (DDI_PROP_DONTPASS), buffer, &arrayp, &cnt); 11535 11536 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) { 11537 /* Check for the global vport setting */ 11538 cnt = 0; 11539 arrayp = NULL; 11540 rval = 11541 ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip, 11542 (DDI_PROP_DONTPASS), "vport", &arrayp, &cnt); 11543 } 11544 11545 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) { 11546 return; 11547 } 11548 11549 for (i = 0; i < cnt; i++) { 11550 errors = 0; 11551 s = (uint8_t *)arrayp[i]; 11552 11553 if (!s) { 11554 break; 11555 } 11556 11557 np = (uint8_t *)&pwwpn; 11558 for (j = 0; j < sizeof (NAME_TYPE); j++) { 11559 c1 = *s++; 11560 if ((c1 >= '0') && (c1 <= '9')) { 11561 sum = ((c1 - '0') << 4); 11562 } else if ((c1 >= 'a') && (c1 <= 'f')) { 11563 sum = ((c1 - 'a' + 10) << 4); 11564 } else if ((c1 >= 'A') && (c1 <= 'F')) { 11565 sum = ((c1 - 'A' + 10) << 4); 11566 } else { 11567 EMLXS_MSGF(EMLXS_CONTEXT, 11568 &emlxs_attach_debug_msg, 11569 "Config error: Invalid PWWPN found. " 11570 "entry=%d byte=%d hi_nibble=%c", 11571 i, j, c1); 11572 errors++; 11573 } 11574 11575 c1 = *s++; 11576 if ((c1 >= '0') && (c1 <= '9')) { 11577 sum |= (c1 - '0'); 11578 } else if ((c1 >= 'a') && (c1 <= 'f')) { 11579 sum |= (c1 - 'a' + 10); 11580 } else if ((c1 >= 'A') && (c1 <= 'F')) { 11581 sum |= (c1 - 'A' + 10); 11582 } else { 11583 EMLXS_MSGF(EMLXS_CONTEXT, 11584 &emlxs_attach_debug_msg, 11585 "Config error: Invalid PWWPN found. " 11586 "entry=%d byte=%d lo_nibble=%c", 11587 i, j, c1); 11588 errors++; 11589 } 11590 11591 *np++ = (uint8_t)sum; 11592 } 11593 11594 if (*s++ != ':') { 11595 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 11596 "Config error: Invalid delimiter after PWWPN. " 11597 "entry=%d", i); 11598 goto out; 11599 } 11600 11601 np = (uint8_t *)&wwnn; 11602 for (j = 0; j < sizeof (NAME_TYPE); j++) { 11603 c1 = *s++; 11604 if ((c1 >= '0') && (c1 <= '9')) { 11605 sum = ((c1 - '0') << 4); 11606 } else if ((c1 >= 'a') && (c1 <= 'f')) { 11607 sum = ((c1 - 'a' + 10) << 4); 11608 } else if ((c1 >= 'A') && (c1 <= 'F')) { 11609 sum = ((c1 - 'A' + 10) << 4); 11610 } else { 11611 EMLXS_MSGF(EMLXS_CONTEXT, 11612 &emlxs_attach_debug_msg, 11613 "Config error: Invalid WWNN found. " 11614 "entry=%d byte=%d hi_nibble=%c", 11615 i, j, c1); 11616 errors++; 11617 } 11618 11619 c1 = *s++; 11620 if ((c1 >= '0') && (c1 <= '9')) { 11621 sum |= (c1 - '0'); 11622 } else if ((c1 >= 'a') && (c1 <= 'f')) { 11623 sum |= (c1 - 'a' + 10); 11624 } else if ((c1 >= 'A') && (c1 <= 'F')) { 11625 sum |= (c1 - 'A' + 10); 11626 } else { 11627 EMLXS_MSGF(EMLXS_CONTEXT, 11628 &emlxs_attach_debug_msg, 11629 "Config error: Invalid WWNN found. " 11630 "entry=%d byte=%d lo_nibble=%c", 11631 i, j, c1); 11632 errors++; 11633 } 11634 11635 *np++ = (uint8_t)sum; 11636 } 11637 11638 if (*s++ != ':') { 11639 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 11640 "Config error: Invalid delimiter after WWNN. " 11641 "entry=%d", i); 11642 goto out; 11643 } 11644 11645 np = (uint8_t *)&wwpn; 11646 for (j = 0; j < sizeof (NAME_TYPE); j++) { 11647 c1 = *s++; 11648 if ((c1 >= '0') && (c1 <= '9')) { 11649 sum = ((c1 - '0') << 4); 11650 } else if ((c1 >= 'a') && (c1 <= 'f')) { 11651 sum = ((c1 - 'a' + 10) << 4); 11652 } else if ((c1 >= 'A') && (c1 <= 'F')) { 11653 sum = ((c1 - 'A' + 10) << 4); 11654 } else { 11655 EMLXS_MSGF(EMLXS_CONTEXT, 11656 &emlxs_attach_debug_msg, 11657 "Config error: Invalid WWPN found. " 11658 "entry=%d byte=%d hi_nibble=%c", 11659 i, j, c1); 11660 11661 errors++; 11662 } 11663 11664 c1 = *s++; 11665 if ((c1 >= '0') && (c1 <= '9')) { 11666 sum |= (c1 - '0'); 11667 } else if ((c1 >= 'a') && (c1 <= 'f')) { 11668 sum |= (c1 - 'a' + 10); 11669 } else if ((c1 >= 'A') && (c1 <= 'F')) { 11670 sum |= (c1 - 'A' + 10); 11671 } else { 11672 EMLXS_MSGF(EMLXS_CONTEXT, 11673 &emlxs_attach_debug_msg, 11674 "Config error: Invalid WWPN found. " 11675 "entry=%d byte=%d lo_nibble=%c", 11676 i, j, c1); 11677 11678 errors++; 11679 } 11680 11681 *np++ = (uint8_t)sum; 11682 } 11683 11684 if (*s++ != ':') { 11685 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 11686 "Config error: Invalid delimiter after WWPN. " 11687 "entry=%d", i); 11688 11689 goto out; 11690 } 11691 11692 sum = 0; 11693 do { 11694 c1 = *s++; 11695 if ((c1 < '0') || (c1 > '9')) { 11696 EMLXS_MSGF(EMLXS_CONTEXT, 11697 &emlxs_attach_debug_msg, 11698 "Config error: Invalid VPI found. " 11699 "entry=%d c=%c vpi=%d", i, c1, sum); 11700 11701 goto out; 11702 } 11703 11704 sum = (sum * 10) + (c1 - '0'); 11705 11706 } while (*s != 0); 11707 11708 vpi = sum; 11709 11710 if (errors) { 11711 continue; 11712 } 11713 11714 /* Entry has been read */ 11715 11716 /* Check if the physical port wwpn */ 11717 /* matches our physical port wwpn */ 11718 if (bcmp((caddr_t)&hba->wwpn, (caddr_t)&pwwpn, 8)) { 11719 continue; 11720 } 11721 11722 /* Check vpi range */ 11723 if ((vpi == 0) || (vpi >= MAX_VPORTS)) { 11724 continue; 11725 } 11726 11727 /* Check if port has already been configured */ 11728 if (hba->port[vpi].flag & EMLXS_PORT_CONFIG) { 11729 continue; 11730 } 11731 11732 /* Set the highest configured vpi */ 11733 if (vpi > hba->vpi_high) { 11734 hba->vpi_high = vpi; 11735 } 11736 11737 bcopy((caddr_t)&wwnn, (caddr_t)&hba->port[vpi].wwnn, 11738 sizeof (NAME_TYPE)); 11739 bcopy((caddr_t)&wwpn, (caddr_t)&hba->port[vpi].wwpn, 11740 sizeof (NAME_TYPE)); 11741 11742 if (hba->port[vpi].snn[0] == 0) { 11743 (void) strncpy((caddr_t)hba->port[vpi].snn, 11744 (caddr_t)hba->snn, 11745 (sizeof (hba->port[vpi].snn)-1)); 11746 } 11747 11748 if (hba->port[vpi].spn[0] == 0) { 11749 (void) snprintf((caddr_t)hba->port[vpi].spn, 11750 sizeof (hba->port[vpi].spn), 11751 "%s VPort-%d", 11752 (caddr_t)hba->spn, vpi); 11753 } 11754 11755 hba->port[vpi].flag |= 11756 (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED); 11757 11758 if (cfg[CFG_VPORT_RESTRICTED].current) { 11759 hba->port[vpi].flag |= EMLXS_PORT_RESTRICTED; 11760 } 11761 } 11762 11763 out: 11764 11765 (void) ddi_prop_free((void *) arrayp); 11766 return; 11767 11768 } /* emlxs_read_vport_prop() */ 11769 #endif /* EMLXS_MODREV3 || EMLXS_MODREV4 */ 11770 11771 11772 extern char * 11773 emlxs_wwn_xlate(char *buffer, size_t len, uint8_t *wwn) 11774 { 11775 (void) snprintf(buffer, len, "%02x%02x%02x%02x%02x%02x%02x%02x", 11776 wwn[0] & 0xff, wwn[1] & 0xff, wwn[2] & 0xff, wwn[3] & 0xff, 11777 wwn[4] & 0xff, wwn[5] & 0xff, wwn[6] & 0xff, wwn[7] & 0xff); 11778 11779 return (buffer); 11780 11781 } /* emlxs_wwn_xlate() */ 11782 11783 11784 extern int32_t 11785 emlxs_wwn_cmp(uint8_t *wwn1, uint8_t *wwn2) 11786 { 11787 uint32_t i; 11788 11789 for (i = 0; i < 8; i ++, wwn1 ++, wwn2 ++) { 11790 if (*wwn1 > *wwn2) { 11791 return (1); 11792 } 11793 if (*wwn1 < *wwn2) { 11794 return (-1); 11795 } 11796 } 11797 11798 return (0); 11799 11800 } /* emlxs_wwn_cmp() */ 11801 11802 11803 /* This is called at port online and offline */ 11804 extern void 11805 emlxs_ub_flush(emlxs_port_t *port) 11806 { 11807 emlxs_hba_t *hba = HBA; 11808 fc_unsol_buf_t *ubp; 11809 emlxs_ub_priv_t *ub_priv; 11810 emlxs_ub_priv_t *next; 11811 11812 /* Return if nothing to do */ 11813 if (!port->ub_wait_head) { 11814 return; 11815 } 11816 11817 mutex_enter(&EMLXS_PORT_LOCK); 11818 ub_priv = port->ub_wait_head; 11819 port->ub_wait_head = NULL; 11820 port->ub_wait_tail = NULL; 11821 mutex_exit(&EMLXS_PORT_LOCK); 11822 11823 while (ub_priv) { 11824 next = ub_priv->next; 11825 ubp = ub_priv->ubp; 11826 11827 /* Check if ULP is online and we have a callback function */ 11828 if (port->ulp_statec != FC_STATE_OFFLINE) { 11829 /* Send ULP the ub buffer */ 11830 emlxs_ulp_unsol_cb(port, ubp); 11831 } else { /* Drop the buffer */ 11832 (void) emlxs_fca_ub_release(port, 1, &ubp->ub_token); 11833 } 11834 11835 ub_priv = next; 11836 11837 } /* while () */ 11838 11839 return; 11840 11841 } /* emlxs_ub_flush() */ 11842 11843 11844 extern void 11845 emlxs_ub_callback(emlxs_port_t *port, fc_unsol_buf_t *ubp) 11846 { 11847 emlxs_hba_t *hba = HBA; 11848 emlxs_ub_priv_t *ub_priv; 11849 11850 ub_priv = ubp->ub_fca_private; 11851 11852 /* Check if ULP is online */ 11853 if (port->ulp_statec != FC_STATE_OFFLINE) { 11854 emlxs_ulp_unsol_cb(port, ubp); 11855 11856 } else { /* ULP offline */ 11857 11858 if (hba->state >= FC_LINK_UP) { 11859 /* Add buffer to queue tail */ 11860 mutex_enter(&EMLXS_PORT_LOCK); 11861 11862 if (port->ub_wait_tail) { 11863 port->ub_wait_tail->next = ub_priv; 11864 } 11865 port->ub_wait_tail = ub_priv; 11866 11867 if (!port->ub_wait_head) { 11868 port->ub_wait_head = ub_priv; 11869 } 11870 11871 mutex_exit(&EMLXS_PORT_LOCK); 11872 } else { 11873 (void) emlxs_fca_ub_release(port, 1, &ubp->ub_token); 11874 } 11875 } 11876 11877 return; 11878 11879 } /* emlxs_ub_callback() */ 11880 11881 11882 extern void 11883 emlxs_fca_link_up(emlxs_port_t *port) 11884 { 11885 emlxs_ulp_statec_cb(port, port->ulp_statec); 11886 return; 11887 11888 } /* emlxs_fca_link_up() */ 11889 11890 11891 extern void 11892 emlxs_fca_link_down(emlxs_port_t *port) 11893 { 11894 emlxs_ulp_statec_cb(port, FC_STATE_OFFLINE); 11895 return; 11896 11897 } /* emlxs_fca_link_down() */ 11898 11899 11900 static uint32_t 11901 emlxs_integrity_check(emlxs_hba_t *hba) 11902 { 11903 uint32_t size; 11904 uint32_t errors = 0; 11905 int ddiinst = hba->ddiinst; 11906 11907 size = 16; 11908 if (sizeof (ULP_BDL) != size) { 11909 cmn_err(CE_WARN, "?%s%d: ULP_BDL size incorrect. %d != 16", 11910 DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDL)); 11911 11912 errors++; 11913 } 11914 size = 8; 11915 if (sizeof (ULP_BDE) != size) { 11916 cmn_err(CE_WARN, "?%s%d: ULP_BDE size incorrect. %d != 8", 11917 DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDE)); 11918 11919 errors++; 11920 } 11921 size = 12; 11922 if (sizeof (ULP_BDE64) != size) { 11923 cmn_err(CE_WARN, "?%s%d: ULP_BDE64 size incorrect. %d != 12", 11924 DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDE64)); 11925 11926 errors++; 11927 } 11928 size = 16; 11929 if (sizeof (HBQE_t) != size) { 11930 cmn_err(CE_WARN, "?%s%d: HBQE size incorrect. %d != 16", 11931 DRIVER_NAME, ddiinst, (int)sizeof (HBQE_t)); 11932 11933 errors++; 11934 } 11935 size = 8; 11936 if (sizeof (HGP) != size) { 11937 cmn_err(CE_WARN, "?%s%d: HGP size incorrect. %d != 8", 11938 DRIVER_NAME, ddiinst, (int)sizeof (HGP)); 11939 11940 errors++; 11941 } 11942 if (sizeof (PGP) != size) { 11943 cmn_err(CE_WARN, "?%s%d: PGP size incorrect. %d != 8", 11944 DRIVER_NAME, ddiinst, (int)sizeof (PGP)); 11945 11946 errors++; 11947 } 11948 size = 4; 11949 if (sizeof (WORD5) != size) { 11950 cmn_err(CE_WARN, "?%s%d: WORD5 size incorrect. %d != 4", 11951 DRIVER_NAME, ddiinst, (int)sizeof (WORD5)); 11952 11953 errors++; 11954 } 11955 size = 124; 11956 if (sizeof (MAILVARIANTS) != size) { 11957 cmn_err(CE_WARN, "?%s%d: MAILVARIANTS size incorrect. " 11958 "%d != 124", DRIVER_NAME, ddiinst, 11959 (int)sizeof (MAILVARIANTS)); 11960 11961 errors++; 11962 } 11963 size = 128; 11964 if (sizeof (SLI1_DESC) != size) { 11965 cmn_err(CE_WARN, "?%s%d: SLI1_DESC size incorrect. %d != 128", 11966 DRIVER_NAME, ddiinst, (int)sizeof (SLI1_DESC)); 11967 11968 errors++; 11969 } 11970 if (sizeof (SLI2_DESC) != size) { 11971 cmn_err(CE_WARN, "?%s%d: SLI2_DESC size incorrect. %d != 128", 11972 DRIVER_NAME, ddiinst, (int)sizeof (SLI2_DESC)); 11973 11974 errors++; 11975 } 11976 size = MBOX_SIZE; 11977 if (sizeof (MAILBOX) != size) { 11978 cmn_err(CE_WARN, "?%s%d: MAILBOX size incorrect. %d != %d", 11979 DRIVER_NAME, ddiinst, (int)sizeof (MAILBOX), MBOX_SIZE); 11980 11981 errors++; 11982 } 11983 size = PCB_SIZE; 11984 if (sizeof (PCB) != size) { 11985 cmn_err(CE_WARN, "?%s%d: PCB size incorrect. %d != %d", 11986 DRIVER_NAME, ddiinst, (int)sizeof (PCB), PCB_SIZE); 11987 11988 errors++; 11989 } 11990 size = 260; 11991 if (sizeof (ATTRIBUTE_ENTRY) != size) { 11992 cmn_err(CE_WARN, "?%s%d: ATTRIBUTE_ENTRY size incorrect. " 11993 "%d != 260", DRIVER_NAME, ddiinst, 11994 (int)sizeof (ATTRIBUTE_ENTRY)); 11995 11996 errors++; 11997 } 11998 size = SLI_SLIM1_SIZE; 11999 if (sizeof (SLIM1) != size) { 12000 cmn_err(CE_WARN, "?%s%d: SLIM1 size incorrect. %d != %d", 12001 DRIVER_NAME, ddiinst, (int)sizeof (SLIM1), SLI_SLIM1_SIZE); 12002 12003 errors++; 12004 } 12005 size = SLI3_IOCB_CMD_SIZE; 12006 if (sizeof (IOCB) != size) { 12007 cmn_err(CE_WARN, "?%s%d: IOCB size incorrect. %d != %d", 12008 DRIVER_NAME, ddiinst, (int)sizeof (IOCB), 12009 SLI3_IOCB_CMD_SIZE); 12010 12011 errors++; 12012 } 12013 12014 size = SLI_SLIM2_SIZE; 12015 if (sizeof (SLIM2) != size) { 12016 cmn_err(CE_WARN, "?%s%d: SLIM2 size incorrect. %d != %d", 12017 DRIVER_NAME, ddiinst, (int)sizeof (SLIM2), 12018 SLI_SLIM2_SIZE); 12019 12020 errors++; 12021 } 12022 return (errors); 12023 12024 } /* emlxs_integrity_check() */ 12025 12026 12027 #ifdef FMA_SUPPORT 12028 /* 12029 * FMA support 12030 */ 12031 12032 extern void 12033 emlxs_fm_init(emlxs_hba_t *hba) 12034 { 12035 ddi_iblock_cookie_t iblk; 12036 12037 if (hba->fm_caps == DDI_FM_NOT_CAPABLE) { 12038 return; 12039 } 12040 12041 if (DDI_FM_ACC_ERR_CAP(hba->fm_caps)) { 12042 emlxs_dev_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC; 12043 emlxs_data_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC; 12044 } 12045 12046 if (DDI_FM_DMA_ERR_CAP(hba->fm_caps)) { 12047 hba->dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR; 12048 hba->dma_attr_ro.dma_attr_flags |= DDI_DMA_FLAGERR; 12049 hba->dma_attr_1sg.dma_attr_flags |= DDI_DMA_FLAGERR; 12050 hba->dma_attr_fcip_rsp.dma_attr_flags |= DDI_DMA_FLAGERR; 12051 } else { 12052 hba->dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12053 hba->dma_attr_ro.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12054 hba->dma_attr_1sg.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12055 hba->dma_attr_fcip_rsp.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12056 } 12057 12058 ddi_fm_init(hba->dip, &hba->fm_caps, &iblk); 12059 12060 if (DDI_FM_EREPORT_CAP(hba->fm_caps) || 12061 DDI_FM_ERRCB_CAP(hba->fm_caps)) { 12062 pci_ereport_setup(hba->dip); 12063 } 12064 12065 if (DDI_FM_ERRCB_CAP(hba->fm_caps)) { 12066 ddi_fm_handler_register(hba->dip, emlxs_fm_error_cb, 12067 (void *)hba); 12068 } 12069 12070 } /* emlxs_fm_init() */ 12071 12072 12073 extern void 12074 emlxs_fm_fini(emlxs_hba_t *hba) 12075 { 12076 if (hba->fm_caps == DDI_FM_NOT_CAPABLE) { 12077 return; 12078 } 12079 12080 if (DDI_FM_EREPORT_CAP(hba->fm_caps) || 12081 DDI_FM_ERRCB_CAP(hba->fm_caps)) { 12082 pci_ereport_teardown(hba->dip); 12083 } 12084 12085 if (DDI_FM_ERRCB_CAP(hba->fm_caps)) { 12086 ddi_fm_handler_unregister(hba->dip); 12087 } 12088 12089 (void) ddi_fm_fini(hba->dip); 12090 12091 } /* emlxs_fm_fini() */ 12092 12093 12094 extern int 12095 emlxs_fm_check_acc_handle(emlxs_hba_t *hba, ddi_acc_handle_t handle) 12096 { 12097 ddi_fm_error_t err; 12098 12099 if (!DDI_FM_ACC_ERR_CAP(hba->fm_caps)) { 12100 return (DDI_FM_OK); 12101 } 12102 12103 /* Some S10 versions do not define the ahi_err structure */ 12104 if (((ddi_acc_impl_t *)handle)->ahi_err == NULL) { 12105 return (DDI_FM_OK); 12106 } 12107 12108 err.fme_status = DDI_FM_OK; 12109 (void) ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION); 12110 12111 /* Some S10 versions do not define the ddi_fm_acc_err_clear function */ 12112 if ((void *)&ddi_fm_acc_err_clear != NULL) { 12113 (void) ddi_fm_acc_err_clear(handle, DDI_FME_VERSION); 12114 } 12115 12116 return (err.fme_status); 12117 12118 } /* emlxs_fm_check_acc_handle() */ 12119 12120 12121 extern int 12122 emlxs_fm_check_dma_handle(emlxs_hba_t *hba, ddi_dma_handle_t handle) 12123 { 12124 ddi_fm_error_t err; 12125 12126 if (!DDI_FM_ACC_ERR_CAP(hba->fm_caps)) { 12127 return (DDI_FM_OK); 12128 } 12129 12130 err.fme_status = DDI_FM_OK; 12131 (void) ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION); 12132 12133 return (err.fme_status); 12134 12135 } /* emlxs_fm_check_dma_handle() */ 12136 12137 12138 extern void 12139 emlxs_fm_ereport(emlxs_hba_t *hba, char *detail) 12140 { 12141 uint64_t ena; 12142 char buf[FM_MAX_CLASS]; 12143 12144 if (!DDI_FM_EREPORT_CAP(hba->fm_caps)) { 12145 return; 12146 } 12147 12148 if (detail == NULL) { 12149 return; 12150 } 12151 12152 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail); 12153 ena = fm_ena_generate(0, FM_ENA_FMT1); 12154 12155 ddi_fm_ereport_post(hba->dip, buf, ena, DDI_NOSLEEP, 12156 FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL); 12157 12158 } /* emlxs_fm_ereport() */ 12159 12160 12161 extern void 12162 emlxs_fm_service_impact(emlxs_hba_t *hba, int impact) 12163 { 12164 if (!DDI_FM_EREPORT_CAP(hba->fm_caps)) { 12165 return; 12166 } 12167 12168 if (impact == NULL) { 12169 return; 12170 } 12171 12172 if ((hba->pm_state & EMLXS_PM_IN_DETACH) && 12173 (impact == DDI_SERVICE_DEGRADED)) { 12174 impact = DDI_SERVICE_UNAFFECTED; 12175 } 12176 12177 ddi_fm_service_impact(hba->dip, impact); 12178 12179 return; 12180 12181 } /* emlxs_fm_service_impact() */ 12182 12183 12184 /* 12185 * The I/O fault service error handling callback function 12186 */ 12187 /*ARGSUSED*/ 12188 extern int 12189 emlxs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, 12190 const void *impl_data) 12191 { 12192 /* 12193 * as the driver can always deal with an error 12194 * in any dma or access handle, we can just return 12195 * the fme_status value. 12196 */ 12197 pci_ereport_post(dip, err, NULL); 12198 return (err->fme_status); 12199 12200 } /* emlxs_fm_error_cb() */ 12201 12202 extern void 12203 emlxs_check_dma(emlxs_hba_t *hba, emlxs_buf_t *sbp) 12204 { 12205 emlxs_port_t *port = sbp->port; 12206 fc_packet_t *pkt = PRIV2PKT(sbp); 12207 12208 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 12209 if (emlxs_fm_check_dma_handle(hba, 12210 hba->sli.sli4.slim2.dma_handle) 12211 != DDI_FM_OK) { 12212 EMLXS_MSGF(EMLXS_CONTEXT, 12213 &emlxs_invalid_dma_handle_msg, 12214 "slim2: hdl=%p", 12215 hba->sli.sli4.slim2.dma_handle); 12216 12217 mutex_enter(&EMLXS_PORT_LOCK); 12218 hba->flag |= FC_DMA_CHECK_ERROR; 12219 mutex_exit(&EMLXS_PORT_LOCK); 12220 } 12221 } else { 12222 if (emlxs_fm_check_dma_handle(hba, 12223 hba->sli.sli3.slim2.dma_handle) 12224 != DDI_FM_OK) { 12225 EMLXS_MSGF(EMLXS_CONTEXT, 12226 &emlxs_invalid_dma_handle_msg, 12227 "slim2: hdl=%p", 12228 hba->sli.sli3.slim2.dma_handle); 12229 12230 mutex_enter(&EMLXS_PORT_LOCK); 12231 hba->flag |= FC_DMA_CHECK_ERROR; 12232 mutex_exit(&EMLXS_PORT_LOCK); 12233 } 12234 } 12235 12236 if (hba->flag & FC_DMA_CHECK_ERROR) { 12237 pkt->pkt_state = FC_PKT_TRAN_ERROR; 12238 pkt->pkt_reason = FC_REASON_DMA_ERROR; 12239 pkt->pkt_expln = FC_EXPLN_NONE; 12240 pkt->pkt_action = FC_ACTION_RETRYABLE; 12241 return; 12242 } 12243 12244 if (pkt->pkt_cmdlen) { 12245 if (emlxs_fm_check_dma_handle(hba, pkt->pkt_cmd_dma) 12246 != DDI_FM_OK) { 12247 EMLXS_MSGF(EMLXS_CONTEXT, 12248 &emlxs_invalid_dma_handle_msg, 12249 "pkt_cmd_dma: hdl=%p", 12250 pkt->pkt_cmd_dma); 12251 12252 pkt->pkt_state = FC_PKT_TRAN_ERROR; 12253 pkt->pkt_reason = FC_REASON_DMA_ERROR; 12254 pkt->pkt_expln = FC_EXPLN_NONE; 12255 pkt->pkt_action = FC_ACTION_RETRYABLE; 12256 12257 return; 12258 } 12259 } 12260 12261 if (pkt->pkt_rsplen) { 12262 if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma) 12263 != DDI_FM_OK) { 12264 EMLXS_MSGF(EMLXS_CONTEXT, 12265 &emlxs_invalid_dma_handle_msg, 12266 "pkt_resp_dma: hdl=%p", 12267 pkt->pkt_resp_dma); 12268 12269 pkt->pkt_state = FC_PKT_TRAN_ERROR; 12270 pkt->pkt_reason = FC_REASON_DMA_ERROR; 12271 pkt->pkt_expln = FC_EXPLN_NONE; 12272 pkt->pkt_action = FC_ACTION_RETRYABLE; 12273 12274 return; 12275 } 12276 } 12277 12278 if (pkt->pkt_datalen) { 12279 if (emlxs_fm_check_dma_handle(hba, pkt->pkt_data_dma) 12280 != DDI_FM_OK) { 12281 EMLXS_MSGF(EMLXS_CONTEXT, 12282 &emlxs_invalid_dma_handle_msg, 12283 "pkt_data_dma: hdl=%p", 12284 pkt->pkt_data_dma); 12285 12286 pkt->pkt_state = FC_PKT_TRAN_ERROR; 12287 pkt->pkt_reason = FC_REASON_DMA_ERROR; 12288 pkt->pkt_expln = FC_EXPLN_NONE; 12289 pkt->pkt_action = FC_ACTION_RETRYABLE; 12290 12291 return; 12292 } 12293 } 12294 12295 return; 12296 12297 } 12298 #endif /* FMA_SUPPORT */ 12299 12300 12301 extern void 12302 emlxs_swap32_buffer(uint8_t *buffer, uint32_t size) 12303 { 12304 uint32_t word; 12305 uint32_t *wptr; 12306 uint32_t i; 12307 12308 VERIFY((size % 4) == 0); 12309 12310 wptr = (uint32_t *)buffer; 12311 12312 for (i = 0; i < size / 4; i++) { 12313 word = *wptr; 12314 *wptr++ = SWAP32(word); 12315 } 12316 12317 return; 12318 12319 } /* emlxs_swap32_buffer() */ 12320 12321 12322 extern void 12323 emlxs_swap32_bcopy(uint8_t *src, uint8_t *dst, uint32_t size) 12324 { 12325 uint32_t word; 12326 uint32_t *sptr; 12327 uint32_t *dptr; 12328 uint32_t i; 12329 12330 VERIFY((size % 4) == 0); 12331 12332 sptr = (uint32_t *)src; 12333 dptr = (uint32_t *)dst; 12334 12335 for (i = 0; i < size / 4; i++) { 12336 word = *sptr++; 12337 *dptr++ = SWAP32(word); 12338 } 12339 12340 return; 12341 12342 } /* emlxs_swap32_buffer() */ 12343 12344 12345 extern char * 12346 emlxs_strtoupper(char *str) 12347 { 12348 char *cptr = str; 12349 12350 while (*cptr) { 12351 if ((*cptr >= 'a') && (*cptr <= 'z')) { 12352 *cptr -= ('a' - 'A'); 12353 } 12354 cptr++; 12355 } 12356 12357 return (str); 12358 12359 } /* emlxs_strtoupper() */ 12360 12361 12362 extern void 12363 emlxs_ulp_statec_cb(emlxs_port_t *port, uint32_t statec) 12364 { 12365 emlxs_hba_t *hba = HBA; 12366 12367 /* This routine coordinates protection with emlxs_fca_unbind_port() */ 12368 12369 mutex_enter(&EMLXS_PORT_LOCK); 12370 if (!(port->flag & EMLXS_INI_BOUND)) { 12371 mutex_exit(&EMLXS_PORT_LOCK); 12372 return; 12373 } 12374 port->ulp_busy++; 12375 mutex_exit(&EMLXS_PORT_LOCK); 12376 12377 port->ulp_statec_cb(port->ulp_handle, statec); 12378 12379 mutex_enter(&EMLXS_PORT_LOCK); 12380 port->ulp_busy--; 12381 mutex_exit(&EMLXS_PORT_LOCK); 12382 12383 return; 12384 12385 } /* emlxs_ulp_statec_cb() */ 12386 12387 12388 extern void 12389 emlxs_ulp_unsol_cb(emlxs_port_t *port, fc_unsol_buf_t *ubp) 12390 { 12391 emlxs_hba_t *hba = HBA; 12392 12393 /* This routine coordinates protection with emlxs_fca_unbind_port() */ 12394 12395 mutex_enter(&EMLXS_PORT_LOCK); 12396 if (!(port->flag & EMLXS_INI_BOUND)) { 12397 mutex_exit(&EMLXS_PORT_LOCK); 12398 return; 12399 } 12400 port->ulp_busy++; 12401 mutex_exit(&EMLXS_PORT_LOCK); 12402 12403 port->ulp_unsol_cb(port->ulp_handle, ubp, ubp->ub_frame.type); 12404 12405 mutex_enter(&EMLXS_PORT_LOCK); 12406 port->ulp_busy--; 12407 mutex_exit(&EMLXS_PORT_LOCK); 12408 12409 return; 12410 12411 } /* emlxs_ulp_unsol_cb() */