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