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 */ 26 27 28 #include <emlxs.h> 29 30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 31 EMLXS_MSG_DEF(EMLXS_SLI3_C); 32 33 static void emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq); 34 static void emlxs_sli3_handle_link_event(emlxs_hba_t *hba); 35 static void emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no, 36 uint32_t ha_copy); 37 #ifdef SFCT_SUPPORT 38 static uint32_t emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp); 39 #endif /* SFCT_SUPPORT */ 40 41 static uint32_t emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp); 42 43 static uint32_t emlxs_disable_traffic_cop = 1; 44 45 static int emlxs_sli3_map_hdw(emlxs_hba_t *hba); 46 47 static void emlxs_sli3_unmap_hdw(emlxs_hba_t *hba); 48 49 static int32_t emlxs_sli3_online(emlxs_hba_t *hba); 50 51 static void emlxs_sli3_offline(emlxs_hba_t *hba); 52 53 static uint32_t emlxs_sli3_hba_reset(emlxs_hba_t *hba, 54 uint32_t restart, uint32_t skip_post, 55 uint32_t quiesce); 56 57 static void emlxs_sli3_hba_kill(emlxs_hba_t *hba); 58 static void emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba); 59 static uint32_t emlxs_sli3_hba_init(emlxs_hba_t *hba); 60 61 static uint32_t emlxs_sli2_bde_setup(emlxs_port_t *port, 62 emlxs_buf_t *sbp); 63 static uint32_t emlxs_sli3_bde_setup(emlxs_port_t *port, 64 emlxs_buf_t *sbp); 65 static uint32_t emlxs_sli2_fct_bde_setup(emlxs_port_t *port, 66 emlxs_buf_t *sbp); 67 static uint32_t emlxs_sli3_fct_bde_setup(emlxs_port_t *port, 68 emlxs_buf_t *sbp); 69 70 71 static void emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba, 72 CHANNEL *rp, IOCBQ *iocb_cmd); 73 74 75 static uint32_t emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, 76 MAILBOXQ *mbq, int32_t flg, 77 uint32_t tmo); 78 79 80 #ifdef SFCT_SUPPORT 81 static uint32_t emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, 82 emlxs_buf_t *cmd_sbp, int channel); 83 84 #endif /* SFCT_SUPPORT */ 85 86 static uint32_t emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port, 87 emlxs_buf_t *sbp, int ring); 88 89 static uint32_t emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, 90 emlxs_buf_t *sbp); 91 92 static uint32_t emlxs_sli3_prep_els_iocb(emlxs_port_t *port, 93 emlxs_buf_t *sbp); 94 95 96 static uint32_t emlxs_sli3_prep_ct_iocb(emlxs_port_t *port, 97 emlxs_buf_t *sbp); 98 99 100 static void emlxs_sli3_poll_intr(emlxs_hba_t *hba, 101 uint32_t att_bit); 102 103 static int32_t emlxs_sli3_intx_intr(char *arg); 104 #ifdef MSI_SUPPORT 105 static uint32_t emlxs_sli3_msi_intr(char *arg1, char *arg2); 106 #endif /* MSI_SUPPORT */ 107 108 static void emlxs_sli3_enable_intr(emlxs_hba_t *hba); 109 110 static void emlxs_sli3_disable_intr(emlxs_hba_t *hba, 111 uint32_t att); 112 113 114 static void emlxs_handle_ff_error(emlxs_hba_t *hba); 115 116 static uint32_t emlxs_handle_mb_event(emlxs_hba_t *hba); 117 118 static void emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba); 119 120 static uint32_t emlxs_mb_config_port(emlxs_hba_t *hba, 121 MAILBOXQ *mbq, uint32_t sli_mode, 122 uint32_t hbainit); 123 static void emlxs_enable_latt(emlxs_hba_t *hba); 124 125 static uint32_t emlxs_check_attention(emlxs_hba_t *hba); 126 127 static uint32_t emlxs_get_attention(emlxs_hba_t *hba, 128 int32_t msgid); 129 static void emlxs_proc_attention(emlxs_hba_t *hba, 130 uint32_t ha_copy); 131 /* static int emlxs_handle_rcv_seq(emlxs_hba_t *hba, */ 132 /* CHANNEL *cp, IOCBQ *iocbq); */ 133 /* static void emlxs_update_HBQ_index(emlxs_hba_t *hba, */ 134 /* uint32_t hbq_id); */ 135 /* static void emlxs_hbq_free_all(emlxs_hba_t *hba, */ 136 /* uint32_t hbq_id); */ 137 static uint32_t emlxs_hbq_setup(emlxs_hba_t *hba, 138 uint32_t hbq_id); 139 extern void emlxs_sli3_timer(emlxs_hba_t *hba); 140 141 extern void emlxs_sli3_poll_erratt(emlxs_hba_t *hba); 142 143 144 /* Define SLI3 API functions */ 145 emlxs_sli_api_t emlxs_sli3_api = { 146 emlxs_sli3_map_hdw, 147 emlxs_sli3_unmap_hdw, 148 emlxs_sli3_online, 149 emlxs_sli3_offline, 150 emlxs_sli3_hba_reset, 151 emlxs_sli3_hba_kill, 152 emlxs_sli3_issue_iocb_cmd, 153 emlxs_sli3_issue_mbox_cmd, 154 #ifdef SFCT_SUPPORT 155 emlxs_sli3_prep_fct_iocb, 156 #else 157 NULL, 158 #endif /* SFCT_SUPPORT */ 159 emlxs_sli3_prep_fcp_iocb, 160 emlxs_sli3_prep_ip_iocb, 161 emlxs_sli3_prep_els_iocb, 162 emlxs_sli3_prep_ct_iocb, 163 emlxs_sli3_poll_intr, 164 emlxs_sli3_intx_intr, 165 emlxs_sli3_msi_intr, 166 emlxs_sli3_disable_intr, 167 emlxs_sli3_timer, 168 emlxs_sli3_poll_erratt 169 }; 170 171 172 /* 173 * emlxs_sli3_online() 174 * 175 * This routine will start initialization of the SLI2/3 HBA. 176 */ 177 static int32_t 178 emlxs_sli3_online(emlxs_hba_t *hba) 179 { 180 emlxs_port_t *port = &PPORT; 181 emlxs_config_t *cfg; 182 emlxs_vpd_t *vpd; 183 MAILBOX *mb = NULL; 184 MAILBOXQ *mbq = NULL; 185 RING *rp; 186 CHANNEL *cp; 187 MATCHMAP *mp = NULL; 188 MATCHMAP *mp1 = NULL; 189 uint8_t *inptr; 190 uint8_t *outptr; 191 uint32_t status; 192 uint16_t i; 193 uint32_t j; 194 uint32_t read_rev_reset; 195 uint32_t key = 0; 196 uint32_t fw_check; 197 uint32_t kern_update = 0; 198 uint32_t rval = 0; 199 uint32_t offset; 200 uint8_t vpd_data[DMP_VPD_SIZE]; 201 uint32_t MaxRbusSize; 202 uint32_t MaxIbusSize; 203 uint32_t sli_mode; 204 uint32_t sli_mode_mask; 205 206 cfg = &CFG; 207 vpd = &VPD; 208 MaxRbusSize = 0; 209 MaxIbusSize = 0; 210 read_rev_reset = 0; 211 hba->chan_count = MAX_RINGS; 212 213 if (hba->bus_type == SBUS_FC) { 214 (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba)); 215 } 216 217 /* Set the fw_check flag */ 218 fw_check = cfg[CFG_FW_CHECK].current; 219 220 if ((fw_check & 0x04) || 221 (hba->fw_flag & FW_UPDATE_KERNEL)) { 222 kern_update = 1; 223 } 224 225 hba->mbox_queue_flag = 0; 226 hba->sli.sli3.hc_copy = 0; 227 hba->fc_edtov = FF_DEF_EDTOV; 228 hba->fc_ratov = FF_DEF_RATOV; 229 hba->fc_altov = FF_DEF_ALTOV; 230 hba->fc_arbtov = FF_DEF_ARBTOV; 231 232 /* 233 * Get a buffer which will be used repeatedly for mailbox commands 234 */ 235 mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP); 236 237 mb = (MAILBOX *)mbq; 238 239 reset: 240 /* Initialize sli mode based on configuration parameter */ 241 switch (cfg[CFG_SLI_MODE].current) { 242 case 2: /* SLI2 mode */ 243 sli_mode = EMLXS_HBA_SLI2_MODE; 244 sli_mode_mask = EMLXS_SLI2_MASK; 245 break; 246 247 case 3: /* SLI3 mode */ 248 sli_mode = EMLXS_HBA_SLI3_MODE; 249 sli_mode_mask = EMLXS_SLI3_MASK; 250 break; 251 252 case 0: /* Best available */ 253 case 1: /* Best available */ 254 default: 255 if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) { 256 sli_mode = EMLXS_HBA_SLI3_MODE; 257 sli_mode_mask = EMLXS_SLI3_MASK; 258 } else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) { 259 sli_mode = EMLXS_HBA_SLI2_MODE; 260 sli_mode_mask = EMLXS_SLI2_MASK; 261 } 262 } 263 /* SBUS adapters only available in SLI2 */ 264 if (hba->bus_type == SBUS_FC) { 265 sli_mode = EMLXS_HBA_SLI2_MODE; 266 sli_mode_mask = EMLXS_SLI2_MASK; 267 } 268 269 /* Reset & Initialize the adapter */ 270 if (emlxs_sli3_hba_init(hba)) { 271 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 272 "Unable to init hba."); 273 274 rval = EIO; 275 goto failed; 276 } 277 278 #ifdef FMA_SUPPORT 279 /* Access handle validation */ 280 if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 281 != DDI_FM_OK) || 282 (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 283 != DDI_FM_OK) || 284 (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle) 285 != DDI_FM_OK)) { 286 EMLXS_MSGF(EMLXS_CONTEXT, 287 &emlxs_invalid_access_handle_msg, NULL); 288 289 rval = EIO; 290 goto failed; 291 } 292 #endif /* FMA_SUPPORT */ 293 294 /* Check for the LP9802 (This is a special case) */ 295 /* We need to check for dual channel adapter */ 296 if (hba->model_info.device_id == PCI_DEVICE_ID_LP9802) { 297 /* Try to determine if this is a DC adapter */ 298 if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) { 299 if (MaxRbusSize == REDUCED_SRAM_CFG) { 300 /* LP9802DC */ 301 for (i = 1; i < emlxs_pci_model_count; i++) { 302 if (emlxs_pci_model[i].id == LP9802DC) { 303 bcopy(&emlxs_pci_model[i], 304 &hba->model_info, 305 sizeof (emlxs_model_t)); 306 break; 307 } 308 } 309 } else if (hba->model_info.id != LP9802) { 310 /* LP9802 */ 311 for (i = 1; i < emlxs_pci_model_count; i++) { 312 if (emlxs_pci_model[i].id == LP9802) { 313 bcopy(&emlxs_pci_model[i], 314 &hba->model_info, 315 sizeof (emlxs_model_t)); 316 break; 317 } 318 } 319 } 320 } 321 } 322 323 /* 324 * Setup and issue mailbox READ REV command 325 */ 326 vpd->opFwRev = 0; 327 vpd->postKernRev = 0; 328 vpd->sli1FwRev = 0; 329 vpd->sli2FwRev = 0; 330 vpd->sli3FwRev = 0; 331 vpd->sli4FwRev = 0; 332 333 vpd->postKernName[0] = 0; 334 vpd->opFwName[0] = 0; 335 vpd->sli1FwName[0] = 0; 336 vpd->sli2FwName[0] = 0; 337 vpd->sli3FwName[0] = 0; 338 vpd->sli4FwName[0] = 0; 339 340 vpd->opFwLabel[0] = 0; 341 vpd->sli1FwLabel[0] = 0; 342 vpd->sli2FwLabel[0] = 0; 343 vpd->sli3FwLabel[0] = 0; 344 vpd->sli4FwLabel[0] = 0; 345 346 /* Sanity check */ 347 if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 348 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 349 "Adapter / SLI mode mismatch mask:x%x", 350 hba->model_info.sli_mask); 351 352 rval = EIO; 353 goto failed; 354 } 355 356 EMLXS_STATE_CHANGE(hba, FC_INIT_REV); 357 emlxs_mb_read_rev(hba, mbq, 0); 358 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 359 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 360 "Unable to read rev. Mailbox cmd=%x status=%x", 361 mb->mbxCommand, mb->mbxStatus); 362 363 rval = EIO; 364 goto failed; 365 } 366 367 if (mb->un.varRdRev.rr == 0) { 368 /* Old firmware */ 369 if (read_rev_reset == 0) { 370 read_rev_reset = 1; 371 372 goto reset; 373 } else { 374 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 375 "Outdated firmware detected."); 376 } 377 378 vpd->rBit = 0; 379 } else { 380 if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) { 381 if (read_rev_reset == 0) { 382 read_rev_reset = 1; 383 384 goto reset; 385 } else { 386 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 387 "Non-operational firmware detected. " 388 "type=%x", 389 mb->un.varRdRev.un.b.ProgType); 390 } 391 } 392 393 vpd->rBit = 1; 394 vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1; 395 bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel, 396 16); 397 vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2; 398 bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel, 399 16); 400 401 /* 402 * Lets try to read the SLI3 version 403 * Setup and issue mailbox READ REV(v3) command 404 */ 405 EMLXS_STATE_CHANGE(hba, FC_INIT_REV); 406 407 /* Reuse mbq from previous mbox */ 408 bzero(mbq, sizeof (MAILBOXQ)); 409 410 emlxs_mb_read_rev(hba, mbq, 1); 411 412 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 413 MBX_SUCCESS) { 414 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 415 "Unable to read rev (v3). Mailbox cmd=%x status=%x", 416 mb->mbxCommand, mb->mbxStatus); 417 418 rval = EIO; 419 goto failed; 420 } 421 422 if (mb->un.varRdRev.rf3) { 423 /* 424 * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1; 425 * Not needed 426 */ 427 vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2; 428 bcopy((char *)mb->un.varRdRev.sliFwName2, 429 vpd->sli3FwLabel, 16); 430 } 431 } 432 433 if ((sli_mode == EMLXS_HBA_SLI3_MODE) && (vpd->sli3FwRev == 0)) { 434 if (vpd->sli2FwRev) { 435 sli_mode = EMLXS_HBA_SLI2_MODE; 436 sli_mode_mask = EMLXS_SLI2_MASK; 437 } else { 438 sli_mode = 0; 439 sli_mode_mask = 0; 440 } 441 } 442 443 else if ((sli_mode == EMLXS_HBA_SLI2_MODE) && (vpd->sli2FwRev == 0)) { 444 if (vpd->sli3FwRev) { 445 sli_mode = EMLXS_HBA_SLI3_MODE; 446 sli_mode_mask = EMLXS_SLI3_MASK; 447 } else { 448 sli_mode = 0; 449 sli_mode_mask = 0; 450 } 451 } 452 453 if (!(hba->model_info.sli_mask & sli_mode_mask)) { 454 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 455 "Firmware not available. sli-mode=%d", 456 cfg[CFG_SLI_MODE].current); 457 458 rval = EIO; 459 goto failed; 460 } 461 462 /* Save information as VPD data */ 463 vpd->postKernRev = mb->un.varRdRev.postKernRev; 464 vpd->opFwRev = mb->un.varRdRev.opFwRev; 465 bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16); 466 vpd->biuRev = mb->un.varRdRev.biuRev; 467 vpd->smRev = mb->un.varRdRev.smRev; 468 vpd->smFwRev = mb->un.varRdRev.un.smFwRev; 469 vpd->endecRev = mb->un.varRdRev.endecRev; 470 vpd->fcphHigh = mb->un.varRdRev.fcphHigh; 471 vpd->fcphLow = mb->un.varRdRev.fcphLow; 472 vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh; 473 vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow; 474 475 /* Decode FW names */ 476 emlxs_decode_version(vpd->postKernRev, vpd->postKernName); 477 emlxs_decode_version(vpd->opFwRev, vpd->opFwName); 478 emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName); 479 emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName); 480 emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName); 481 emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName); 482 483 /* Decode FW labels */ 484 emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel, 1); 485 emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel, 1); 486 emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel, 1); 487 emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel, 1); 488 emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel, 1); 489 490 /* Reuse mbq from previous mbox */ 491 bzero(mbq, sizeof (MAILBOXQ)); 492 493 key = emlxs_get_key(hba, mbq); 494 495 /* Get adapter VPD information */ 496 offset = 0; 497 bzero(vpd_data, sizeof (vpd_data)); 498 vpd->port_index = (uint32_t)-1; 499 500 while (offset < DMP_VPD_SIZE) { 501 /* Reuse mbq from previous mbox */ 502 bzero(mbq, sizeof (MAILBOXQ)); 503 504 emlxs_mb_dump_vpd(hba, mbq, offset); 505 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 506 MBX_SUCCESS) { 507 /* 508 * Let it go through even if failed. 509 * Not all adapter's have VPD info and thus will 510 * fail here. This is not a problem 511 */ 512 513 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 514 "No VPD found. offset=%x status=%x", offset, 515 mb->mbxStatus); 516 break; 517 } else { 518 if (mb->un.varDmp.ra == 1) { 519 uint32_t *lp1, *lp2; 520 uint32_t bsize; 521 uint32_t wsize; 522 523 /* 524 * mb->un.varDmp.word_cnt is actually byte 525 * count for the dump reply 526 */ 527 bsize = mb->un.varDmp.word_cnt; 528 529 /* Stop if no data was received */ 530 if (bsize == 0) { 531 break; 532 } 533 534 /* Check limit on byte size */ 535 bsize = (bsize > 536 (sizeof (vpd_data) - offset)) ? 537 (sizeof (vpd_data) - offset) : bsize; 538 539 /* 540 * Convert size from bytes to words with 541 * minimum of 1 word 542 */ 543 wsize = (bsize > 4) ? (bsize >> 2) : 1; 544 545 /* 546 * Transfer data into vpd_data buffer one 547 * word at a time 548 */ 549 lp1 = (uint32_t *)&mb->un.varDmp.resp_offset; 550 lp2 = (uint32_t *)&vpd_data[offset]; 551 552 for (i = 0; i < wsize; i++) { 553 status = *lp1++; 554 *lp2++ = BE_SWAP32(status); 555 } 556 557 /* Increment total byte count saved */ 558 offset += (wsize << 2); 559 560 /* 561 * Stop if less than a full transfer was 562 * received 563 */ 564 if (wsize < DMP_VPD_DUMP_WCOUNT) { 565 break; 566 } 567 568 } else { 569 EMLXS_MSGF(EMLXS_CONTEXT, 570 &emlxs_init_debug_msg, 571 "No VPD acknowledgment. offset=%x", 572 offset); 573 break; 574 } 575 } 576 577 } 578 579 if (vpd_data[0]) { 580 (void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset); 581 582 /* 583 * If there is a VPD part number, and it does not 584 * match the current default HBA model info, 585 * replace the default data with an entry that 586 * does match. 587 * 588 * After emlxs_parse_vpd model holds the VPD value 589 * for V2 and part_num hold the value for PN. These 590 * 2 values are NOT necessarily the same. 591 */ 592 593 rval = 0; 594 if ((vpd->model[0] != 0) && 595 (strcmp(&vpd->model[0], hba->model_info.model) != 0)) { 596 597 /* First scan for a V2 match */ 598 599 for (i = 1; i < emlxs_pci_model_count; i++) { 600 if (strcmp(&vpd->model[0], 601 emlxs_pci_model[i].model) == 0) { 602 bcopy(&emlxs_pci_model[i], 603 &hba->model_info, 604 sizeof (emlxs_model_t)); 605 rval = 1; 606 break; 607 } 608 } 609 } 610 611 if (!rval && (vpd->part_num[0] != 0) && 612 (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) { 613 614 /* Next scan for a PN match */ 615 616 for (i = 1; i < emlxs_pci_model_count; i++) { 617 if (strcmp(&vpd->part_num[0], 618 emlxs_pci_model[i].model) == 0) { 619 bcopy(&emlxs_pci_model[i], 620 &hba->model_info, 621 sizeof (emlxs_model_t)); 622 break; 623 } 624 } 625 } 626 627 /* 628 * Now lets update hba->model_info with the real 629 * VPD data, if any. 630 */ 631 632 /* 633 * Replace the default model description with vpd data 634 */ 635 if (vpd->model_desc[0] != 0) { 636 (void) strcpy(hba->model_info.model_desc, 637 vpd->model_desc); 638 } 639 640 /* Replace the default model with vpd data */ 641 if (vpd->model[0] != 0) { 642 (void) strcpy(hba->model_info.model, vpd->model); 643 } 644 645 /* Replace the default program types with vpd data */ 646 if (vpd->prog_types[0] != 0) { 647 emlxs_parse_prog_types(hba, vpd->prog_types); 648 } 649 } 650 651 /* 652 * Since the adapter model may have changed with the vpd data 653 * lets double check if adapter is not supported 654 */ 655 if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { 656 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 657 "Unsupported adapter found. " 658 "Id:%d Device id:0x%x SSDID:0x%x Model:%s", 659 hba->model_info.id, hba->model_info.device_id, 660 hba->model_info.ssdid, hba->model_info.model); 661 662 rval = EIO; 663 goto failed; 664 } 665 666 /* Read the adapter's wakeup parms */ 667 (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 668 emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 669 vpd->boot_version); 670 671 /* Get fcode version property */ 672 emlxs_get_fcode_version(hba); 673 674 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 675 "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev, 676 vpd->opFwRev, vpd->sli1FwRev); 677 678 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 679 "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev, 680 vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh); 681 682 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 683 "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version); 684 685 /* 686 * If firmware checking is enabled and the adapter model indicates 687 * a firmware image, then perform firmware version check 688 */ 689 hba->fw_flag = 0; 690 hba->fw_timer = 0; 691 692 if (((fw_check & 0x1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) && 693 hba->model_info.fwid) || ((fw_check & 0x2) && 694 hba->model_info.fwid)) { 695 emlxs_firmware_t *fw; 696 697 /* Find firmware image indicated by adapter model */ 698 fw = NULL; 699 for (i = 0; i < emlxs_fw_count; i++) { 700 if (emlxs_fw_table[i].id == hba->model_info.fwid) { 701 fw = &emlxs_fw_table[i]; 702 break; 703 } 704 } 705 706 /* 707 * If the image was found, then verify current firmware 708 * versions of adapter 709 */ 710 if (fw) { 711 if (!kern_update && 712 ((fw->kern && (vpd->postKernRev != fw->kern)) || 713 (fw->stub && (vpd->opFwRev != fw->stub)))) { 714 715 hba->fw_flag |= FW_UPDATE_NEEDED; 716 717 } else if ((fw->kern && (vpd->postKernRev != 718 fw->kern)) || 719 (fw->stub && (vpd->opFwRev != fw->stub)) || 720 (fw->sli1 && (vpd->sli1FwRev != fw->sli1)) || 721 (fw->sli2 && (vpd->sli2FwRev != fw->sli2)) || 722 (fw->sli3 && (vpd->sli3FwRev != fw->sli3)) || 723 (fw->sli4 && (vpd->sli4FwRev != fw->sli4))) { 724 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 725 "Firmware update needed. " 726 "Updating. id=%d fw=%d", 727 hba->model_info.id, hba->model_info.fwid); 728 729 #ifdef MODFW_SUPPORT 730 /* 731 * Load the firmware image now 732 * If MODFW_SUPPORT is not defined, the 733 * firmware image will already be defined 734 * in the emlxs_fw_table 735 */ 736 emlxs_fw_load(hba, fw); 737 #endif /* MODFW_SUPPORT */ 738 739 if (fw->image && fw->size) { 740 if (emlxs_fw_download(hba, 741 (char *)fw->image, fw->size, 0)) { 742 EMLXS_MSGF(EMLXS_CONTEXT, 743 &emlxs_init_msg, 744 "Firmware update failed."); 745 746 hba->fw_flag |= 747 FW_UPDATE_NEEDED; 748 } 749 #ifdef MODFW_SUPPORT 750 /* 751 * Unload the firmware image from 752 * kernel memory 753 */ 754 emlxs_fw_unload(hba, fw); 755 #endif /* MODFW_SUPPORT */ 756 757 fw_check = 0; 758 759 goto reset; 760 } 761 762 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 763 "Firmware image unavailable."); 764 } else { 765 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 766 "Firmware update not needed."); 767 } 768 } else { 769 /* This should not happen */ 770 771 /* 772 * This means either the adapter database is not 773 * correct or a firmware image is missing from the 774 * compile 775 */ 776 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 777 "Firmware image unavailable. id=%d fw=%d", 778 hba->model_info.id, hba->model_info.fwid); 779 } 780 } 781 782 /* 783 * Add our interrupt routine to kernel's interrupt chain & enable it 784 * If MSI is enabled this will cause Solaris to program the MSI address 785 * and data registers in PCI config space 786 */ 787 if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) { 788 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 789 "Unable to add interrupt(s)."); 790 791 rval = EIO; 792 goto failed; 793 } 794 795 EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT); 796 797 /* Reuse mbq from previous mbox */ 798 bzero(mbq, sizeof (MAILBOXQ)); 799 800 (void) emlxs_mb_config_port(hba, mbq, sli_mode, key); 801 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 802 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 803 "Unable to configure port. " 804 "Mailbox cmd=%x status=%x slimode=%d key=%x", 805 mb->mbxCommand, mb->mbxStatus, sli_mode, key); 806 807 for (sli_mode--; sli_mode > 0; sli_mode--) { 808 /* Check if sli_mode is supported by this adapter */ 809 if (hba->model_info.sli_mask & 810 EMLXS_SLI_MASK(sli_mode)) { 811 sli_mode_mask = EMLXS_SLI_MASK(sli_mode); 812 break; 813 } 814 } 815 816 if (sli_mode) { 817 fw_check = 0; 818 819 goto reset; 820 } 821 822 hba->flag &= ~FC_SLIM2_MODE; 823 824 rval = EIO; 825 goto failed; 826 } 827 828 /* Check if SLI3 mode was achieved */ 829 if (mb->un.varCfgPort.rMA && 830 (mb->un.varCfgPort.sli_mode == EMLXS_HBA_SLI3_MODE)) { 831 832 if (mb->un.varCfgPort.vpi_max > 1) { 833 hba->flag |= FC_NPIV_ENABLED; 834 835 if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 836 hba->vpi_max = 837 min(mb->un.varCfgPort.vpi_max, 838 MAX_VPORTS - 1); 839 } else { 840 hba->vpi_max = 841 min(mb->un.varCfgPort.vpi_max, 842 MAX_VPORTS_LIMITED - 1); 843 } 844 } 845 846 #if (EMLXS_MODREV >= EMLXS_MODREV5) 847 hba->fca_tran->fca_num_npivports = 848 (cfg[CFG_NPIV_ENABLE].current) ? hba->vpi_max : 0; 849 #endif /* >= EMLXS_MODREV5 */ 850 851 if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) { 852 hba->flag |= FC_HBQ_ENABLED; 853 } 854 855 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 856 "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max); 857 } else { 858 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 859 "SLI2 mode: flag=%x", hba->flag); 860 sli_mode = EMLXS_HBA_SLI2_MODE; 861 sli_mode_mask = EMLXS_SLI2_MASK; 862 hba->sli_mode = sli_mode; 863 } 864 865 /* Get and save the current firmware version (based on sli_mode) */ 866 emlxs_decode_firmware_rev(hba, vpd); 867 868 emlxs_pcix_mxr_update(hba, 0); 869 870 /* Reuse mbq from previous mbox */ 871 bzero(mbq, sizeof (MAILBOXQ)); 872 873 emlxs_mb_read_config(hba, mbq); 874 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 875 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 876 "Unable to read configuration. Mailbox cmd=%x status=%x", 877 mb->mbxCommand, mb->mbxStatus); 878 879 rval = EIO; 880 goto failed; 881 } 882 883 /* Save the link speed capabilities */ 884 vpd->link_speed = (uint16_t)mb->un.varRdConfig.lmt; 885 emlxs_process_link_speed(hba); 886 887 /* Set the max node count */ 888 if (cfg[CFG_NUM_NODES].current > 0) { 889 hba->max_nodes = 890 min(cfg[CFG_NUM_NODES].current, 891 mb->un.varRdConfig.max_rpi); 892 } else { 893 hba->max_nodes = mb->un.varRdConfig.max_rpi; 894 } 895 896 /* Set the io throttle */ 897 hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE; 898 hba->max_iotag = mb->un.varRdConfig.max_xri; 899 900 /* 901 * Allocate some memory for buffers 902 */ 903 if (emlxs_mem_alloc_buffer(hba) == 0) { 904 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 905 "Unable to allocate memory buffers."); 906 907 EMLXS_STATE_CHANGE(hba, FC_ERROR); 908 return (ENOMEM); 909 } 910 911 /* 912 * Setup and issue mailbox RUN BIU DIAG command Setup test buffers 913 */ 914 if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) || 915 ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0)) { 916 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 917 "Unable to allocate diag buffers."); 918 919 rval = ENOMEM; 920 goto failed; 921 } 922 923 bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt, 924 MEM_ELSBUF_SIZE); 925 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, MEM_ELSBUF_SIZE, 926 DDI_DMA_SYNC_FORDEV); 927 928 bzero(mp1->virt, MEM_ELSBUF_SIZE); 929 EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 930 DDI_DMA_SYNC_FORDEV); 931 932 /* Reuse mbq from previous mbox */ 933 bzero(mbq, sizeof (MAILBOXQ)); 934 935 (void) emlxs_mb_run_biu_diag(hba, mbq, mp->phys, mp1->phys); 936 937 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 938 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 939 "Unable to run BIU diag. Mailbox cmd=%x status=%x", 940 mb->mbxCommand, mb->mbxStatus); 941 942 rval = EIO; 943 goto failed; 944 } 945 946 EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 947 DDI_DMA_SYNC_FORKERNEL); 948 949 #ifdef FMA_SUPPORT 950 if (mp->dma_handle) { 951 if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) 952 != DDI_FM_OK) { 953 EMLXS_MSGF(EMLXS_CONTEXT, 954 &emlxs_invalid_dma_handle_msg, 955 "emlxs_sli3_online: hdl=%p", 956 mp->dma_handle); 957 rval = EIO; 958 goto failed; 959 } 960 } 961 962 if (mp1->dma_handle) { 963 if (emlxs_fm_check_dma_handle(hba, mp1->dma_handle) 964 != DDI_FM_OK) { 965 EMLXS_MSGF(EMLXS_CONTEXT, 966 &emlxs_invalid_dma_handle_msg, 967 "emlxs_sli3_online: hdl=%p", 968 mp1->dma_handle); 969 rval = EIO; 970 goto failed; 971 } 972 } 973 #endif /* FMA_SUPPORT */ 974 975 outptr = mp->virt; 976 inptr = mp1->virt; 977 978 for (i = 0; i < MEM_ELSBUF_SIZE; i++) { 979 if (*outptr++ != *inptr++) { 980 outptr--; 981 inptr--; 982 983 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 984 "BIU diagnostic failed. " 985 "offset %x value %x should be %x.", 986 i, (uint32_t)*inptr, (uint32_t)*outptr); 987 988 rval = EIO; 989 goto failed; 990 } 991 } 992 993 /* Free the buffers since we were polling */ 994 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 995 mp = NULL; 996 emlxs_mem_put(hba, MEM_BUF, (void *)mp1); 997 mp1 = NULL; 998 999 hba->channel_fcp = FC_FCP_RING; 1000 hba->channel_els = FC_ELS_RING; 1001 hba->channel_ip = FC_IP_RING; 1002 hba->channel_ct = FC_CT_RING; 1003 hba->sli.sli3.ring_count = MAX_RINGS; 1004 1005 hba->channel_tx_count = 0; 1006 hba->io_count = 0; 1007 hba->fc_iotag = 1; 1008 1009 /* 1010 * OutOfRange (oor) iotags are used for abort or 1011 * close XRI commands 1012 */ 1013 hba->fc_oor_iotag = hba->max_iotag; 1014 1015 for (i = 0; i < hba->chan_count; i++) { 1016 cp = &hba->chan[i]; 1017 1018 /* 1 to 1 mapping between ring and channel */ 1019 cp->iopath = (void *)&hba->sli.sli3.ring[i]; 1020 1021 cp->hba = hba; 1022 cp->channelno = i; 1023 } 1024 1025 /* 1026 * Setup and issue mailbox CONFIGURE RING command 1027 */ 1028 for (i = 0; i < (uint32_t)hba->sli.sli3.ring_count; i++) { 1029 /* 1030 * Initialize cmd/rsp ring pointers 1031 */ 1032 rp = &hba->sli.sli3.ring[i]; 1033 1034 /* 1 to 1 mapping between ring and channel */ 1035 rp->channelp = &hba->chan[i]; 1036 1037 rp->hba = hba; 1038 rp->ringno = (uint8_t)i; 1039 1040 rp->fc_cmdidx = 0; 1041 rp->fc_rspidx = 0; 1042 EMLXS_STATE_CHANGE(hba, FC_INIT_CFGRING); 1043 1044 /* Reuse mbq from previous mbox */ 1045 bzero(mbq, sizeof (MAILBOXQ)); 1046 1047 emlxs_mb_config_ring(hba, i, mbq); 1048 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 1049 MBX_SUCCESS) { 1050 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1051 "Unable to configure ring. " 1052 "Mailbox cmd=%x status=%x", 1053 mb->mbxCommand, mb->mbxStatus); 1054 1055 rval = EIO; 1056 goto failed; 1057 } 1058 } 1059 1060 /* 1061 * Setup link timers 1062 */ 1063 EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK); 1064 1065 /* Reuse mbq from previous mbox */ 1066 bzero(mbq, sizeof (MAILBOXQ)); 1067 1068 emlxs_mb_config_link(hba, mbq); 1069 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 1070 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1071 "Unable to configure link. Mailbox cmd=%x status=%x", 1072 mb->mbxCommand, mb->mbxStatus); 1073 1074 rval = EIO; 1075 goto failed; 1076 } 1077 1078 #ifdef MAX_RRDY_SUPPORT 1079 /* Set MAX_RRDY if one is provided */ 1080 if (cfg[CFG_MAX_RRDY].current) { 1081 1082 /* Reuse mbq from previous mbox */ 1083 bzero(mbq, sizeof (MAILBOXQ)); 1084 1085 emlxs_mb_set_var(hba, (MAILBOX *)mbq, 0x00060412, 1086 cfg[CFG_MAX_RRDY].current); 1087 1088 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 1089 MBX_SUCCESS) { 1090 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1091 "MAX_RRDY: Unable to set. status=%x " \ 1092 "value=%d", 1093 mb->mbxStatus, cfg[CFG_MAX_RRDY].current); 1094 } else { 1095 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1096 "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current); 1097 } 1098 } 1099 #endif /* MAX_RRDY_SUPPORT */ 1100 1101 /* Reuse mbq from previous mbox */ 1102 bzero(mbq, sizeof (MAILBOXQ)); 1103 1104 /* 1105 * We need to get login parameters for NID 1106 */ 1107 (void) emlxs_mb_read_sparam(hba, mbq); 1108 mp = (MATCHMAP *)mbq->bp; 1109 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 1110 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1111 "Unable to read parameters. Mailbox cmd=%x status=%x", 1112 mb->mbxCommand, mb->mbxStatus); 1113 1114 rval = EIO; 1115 goto failed; 1116 } 1117 1118 /* Free the buffer since we were polling */ 1119 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 1120 mp = NULL; 1121 1122 /* If no serial number in VPD data, then use the WWPN */ 1123 if (vpd->serial_num[0] == 0) { 1124 outptr = (uint8_t *)&hba->wwpn.IEEE[0]; 1125 for (i = 0; i < 12; i++) { 1126 status = *outptr++; 1127 j = ((status & 0xf0) >> 4); 1128 if (j <= 9) { 1129 vpd->serial_num[i] = 1130 (char)((uint8_t)'0' + (uint8_t)j); 1131 } else { 1132 vpd->serial_num[i] = 1133 (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1134 } 1135 1136 i++; 1137 j = (status & 0xf); 1138 if (j <= 9) { 1139 vpd->serial_num[i] = 1140 (char)((uint8_t)'0' + (uint8_t)j); 1141 } else { 1142 vpd->serial_num[i] = 1143 (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1144 } 1145 } 1146 1147 /* 1148 * Set port number and port index to zero 1149 * The WWN's are unique to each port and therefore port_num 1150 * must equal zero. This effects the hba_fru_details structure 1151 * in fca_bind_port() 1152 */ 1153 vpd->port_num[0] = 0; 1154 vpd->port_index = 0; 1155 } 1156 1157 /* 1158 * Make first attempt to set a port index 1159 * Check if this is a multifunction adapter 1160 */ 1161 if ((vpd->port_index == (uint32_t)-1) && 1162 (hba->model_info.chip >= EMLXS_THOR_CHIP)) { 1163 char *buffer; 1164 int32_t i; 1165 1166 /* 1167 * The port address looks like this: 1168 * 1 - for port index 0 1169 * 1,1 - for port index 1 1170 * 1,2 - for port index 2 1171 */ 1172 buffer = ddi_get_name_addr(hba->dip); 1173 1174 if (buffer) { 1175 vpd->port_index = 0; 1176 1177 /* Reverse scan for a comma */ 1178 for (i = strlen(buffer) - 1; i > 0; i--) { 1179 if (buffer[i] == ',') { 1180 /* Comma found - set index now */ 1181 vpd->port_index = 1182 emlxs_strtol(&buffer[i + 1], 10); 1183 break; 1184 } 1185 } 1186 } 1187 } 1188 1189 /* Make final attempt to set a port index */ 1190 if (vpd->port_index == (uint32_t)-1) { 1191 dev_info_t *p_dip; 1192 dev_info_t *c_dip; 1193 1194 p_dip = ddi_get_parent(hba->dip); 1195 c_dip = ddi_get_child(p_dip); 1196 1197 vpd->port_index = 0; 1198 while (c_dip && (hba->dip != c_dip)) { 1199 c_dip = ddi_get_next_sibling(c_dip); 1200 vpd->port_index++; 1201 } 1202 } 1203 1204 if (vpd->port_num[0] == 0) { 1205 if (hba->model_info.channels > 1) { 1206 (void) sprintf(vpd->port_num, "%d", vpd->port_index); 1207 } 1208 } 1209 1210 if (vpd->id[0] == 0) { 1211 (void) strcpy(vpd->id, hba->model_info.model_desc); 1212 } 1213 1214 if (vpd->manufacturer[0] == 0) { 1215 (void) strcpy(vpd->manufacturer, hba->model_info.manufacturer); 1216 } 1217 1218 if (vpd->part_num[0] == 0) { 1219 (void) strcpy(vpd->part_num, hba->model_info.model); 1220 } 1221 1222 if (vpd->model_desc[0] == 0) { 1223 (void) strcpy(vpd->model_desc, hba->model_info.model_desc); 1224 } 1225 1226 if (vpd->model[0] == 0) { 1227 (void) strcpy(vpd->model, hba->model_info.model); 1228 } 1229 1230 if (vpd->prog_types[0] == 0) { 1231 emlxs_build_prog_types(hba, vpd->prog_types); 1232 } 1233 1234 /* Create the symbolic names */ 1235 (void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s", 1236 hba->model_info.model, hba->vpd.fw_version, emlxs_version, 1237 (char *)utsname.nodename); 1238 1239 (void) sprintf(hba->spn, 1240 "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 1241 hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, 1242 hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], 1243 hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 1244 1245 if (cfg[CFG_NETWORK_ON].current) { 1246 if ((hba->sparam.portName.nameType != NAME_IEEE) || 1247 (hba->sparam.portName.IEEEextMsn != 0) || 1248 (hba->sparam.portName.IEEEextLsb != 0)) { 1249 1250 cfg[CFG_NETWORK_ON].current = 0; 1251 1252 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1253 "WWPN doesn't conform to IP profile: nameType=%x", 1254 hba->sparam.portName.nameType); 1255 } 1256 1257 /* Reuse mbq from previous mbox */ 1258 bzero(mbq, sizeof (MAILBOXQ)); 1259 1260 /* Issue CONFIG FARP */ 1261 emlxs_mb_config_farp(hba, mbq); 1262 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 1263 MBX_SUCCESS) { 1264 /* 1265 * Let it go through even if failed. 1266 */ 1267 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1268 "Unable to configure FARP. " 1269 "Mailbox cmd=%x status=%x", 1270 mb->mbxCommand, mb->mbxStatus); 1271 } 1272 } 1273 #ifdef MSI_SUPPORT 1274 /* Configure MSI map if required */ 1275 if (hba->intr_count > 1) { 1276 1277 if (hba->intr_type == DDI_INTR_TYPE_MSIX) { 1278 /* always start from 0 */ 1279 hba->last_msiid = 0; 1280 } 1281 1282 /* Reuse mbq from previous mbox */ 1283 bzero(mbq, sizeof (MAILBOXQ)); 1284 1285 emlxs_mb_config_msix(hba, mbq, hba->intr_map, hba->intr_count); 1286 1287 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) == 1288 MBX_SUCCESS) { 1289 goto msi_configured; 1290 } 1291 1292 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1293 "Unable to config MSIX. Mailbox cmd=0x%x status=0x%x", 1294 mb->mbxCommand, mb->mbxStatus); 1295 1296 /* Reuse mbq from previous mbox */ 1297 bzero(mbq, sizeof (MAILBOXQ)); 1298 1299 emlxs_mb_config_msi(hba, mbq, hba->intr_map, hba->intr_count); 1300 1301 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) == 1302 MBX_SUCCESS) { 1303 goto msi_configured; 1304 } 1305 1306 1307 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1308 "Unable to config MSI. Mailbox cmd=0x%x status=0x%x", 1309 mb->mbxCommand, mb->mbxStatus); 1310 1311 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1312 "Attempting single interrupt mode..."); 1313 1314 /* First cleanup old interrupts */ 1315 (void) emlxs_msi_remove(hba); 1316 (void) emlxs_msi_uninit(hba); 1317 1318 status = emlxs_msi_init(hba, 1); 1319 1320 if (status != DDI_SUCCESS) { 1321 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1322 "Unable to initialize interrupt. status=%d", 1323 status); 1324 1325 rval = EIO; 1326 goto failed; 1327 } 1328 1329 /* 1330 * Reset adapter - The adapter needs to be reset because 1331 * the bus cannot handle the MSI change without handshaking 1332 * with the adapter again 1333 */ 1334 1335 (void) emlxs_mem_free_buffer(hba); 1336 fw_check = 0; 1337 goto reset; 1338 } 1339 1340 msi_configured: 1341 1342 1343 if ((hba->intr_count >= 1) && 1344 (hba->sli_mode == EMLXS_HBA_SLI3_MODE)) { 1345 /* intr_count is a sequence of msi id */ 1346 /* Setup msi2chan[msi_id] */ 1347 for (i = 0; i < hba->intr_count; i ++) { 1348 hba->msi2chan[i] = i; 1349 if (i >= hba->chan_count) 1350 hba->msi2chan[i] = (i - hba->chan_count); 1351 } 1352 } 1353 #endif /* MSI_SUPPORT */ 1354 1355 /* 1356 * We always disable the firmware traffic cop feature 1357 */ 1358 if (emlxs_disable_traffic_cop) { 1359 /* Reuse mbq from previous mbox */ 1360 bzero(mbq, sizeof (MAILBOXQ)); 1361 1362 emlxs_disable_tc(hba, mbq); 1363 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 1364 MBX_SUCCESS) { 1365 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1366 "Unable to disable traffic cop. " 1367 "Mailbox cmd=%x status=%x", 1368 mb->mbxCommand, mb->mbxStatus); 1369 1370 rval = EIO; 1371 goto failed; 1372 } 1373 } 1374 1375 1376 /* Reuse mbq from previous mbox */ 1377 bzero(mbq, sizeof (MAILBOXQ)); 1378 1379 /* Register for async events */ 1380 emlxs_mb_async_event(hba, mbq); 1381 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 1382 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1383 "Async events disabled. Mailbox status=%x", 1384 mb->mbxStatus); 1385 } else { 1386 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1387 "Async events enabled."); 1388 hba->flag |= FC_ASYNC_EVENTS; 1389 } 1390 1391 EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN); 1392 1393 emlxs_sli3_enable_intr(hba); 1394 1395 if (hba->flag & FC_HBQ_ENABLED) { 1396 if (hba->tgt_mode) { 1397 if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) { 1398 EMLXS_MSGF(EMLXS_CONTEXT, 1399 &emlxs_init_failed_msg, 1400 "Unable to setup FCT HBQ."); 1401 1402 rval = ENOMEM; 1403 goto failed; 1404 } 1405 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1406 "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1407 } 1408 1409 if (cfg[CFG_NETWORK_ON].current) { 1410 if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) { 1411 EMLXS_MSGF(EMLXS_CONTEXT, 1412 &emlxs_init_failed_msg, 1413 "Unable to setup IP HBQ."); 1414 1415 rval = ENOMEM; 1416 goto failed; 1417 } 1418 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1419 "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1420 } 1421 1422 if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) { 1423 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1424 "Unable to setup ELS HBQ."); 1425 rval = ENOMEM; 1426 goto failed; 1427 } 1428 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1429 "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1430 1431 if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) { 1432 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1433 "Unable to setup CT HBQ."); 1434 1435 rval = ENOMEM; 1436 goto failed; 1437 } 1438 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1439 "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1440 } else { 1441 if (hba->tgt_mode) { 1442 /* Post the FCT unsol buffers */ 1443 rp = &hba->sli.sli3.ring[FC_FCT_RING]; 1444 for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) { 1445 (void) emlxs_post_buffer(hba, rp, 2); 1446 } 1447 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1448 "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1449 } 1450 1451 if (cfg[CFG_NETWORK_ON].current) { 1452 /* Post the IP unsol buffers */ 1453 rp = &hba->sli.sli3.ring[FC_IP_RING]; 1454 for (j = 0; j < MEM_IPBUF_COUNT; j += 2) { 1455 (void) emlxs_post_buffer(hba, rp, 2); 1456 } 1457 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1458 "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1459 } 1460 1461 /* Post the ELS unsol buffers */ 1462 rp = &hba->sli.sli3.ring[FC_ELS_RING]; 1463 for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) { 1464 (void) emlxs_post_buffer(hba, rp, 2); 1465 } 1466 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1467 "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1468 1469 1470 /* Post the CT unsol buffers */ 1471 rp = &hba->sli.sli3.ring[FC_CT_RING]; 1472 for (j = 0; j < MEM_CTBUF_COUNT; j += 2) { 1473 (void) emlxs_post_buffer(hba, rp, 2); 1474 } 1475 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1476 "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1477 } 1478 1479 (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); 1480 1481 /* 1482 * Setup and issue mailbox INITIALIZE LINK command 1483 * At this point, the interrupt will be generated by the HW 1484 * Do this only if persist-linkdown is not set 1485 */ 1486 if (cfg[CFG_PERSIST_LINKDOWN].current == 0) { 1487 mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1); 1488 if (mbq == NULL) { 1489 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1490 "Unable to allocate mailbox buffer."); 1491 1492 rval = EIO; 1493 goto failed; 1494 } 1495 1496 emlxs_mb_init_link(hba, mbq, cfg[CFG_TOPOLOGY].current, 1497 cfg[CFG_LINK_SPEED].current); 1498 1499 rval = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 1500 if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) { 1501 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1502 "Unable to initialize link. " \ 1503 "Mailbox cmd=%x status=%x", 1504 mb->mbxCommand, mb->mbxStatus); 1505 1506 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 1507 mbq = NULL; 1508 rval = EIO; 1509 goto failed; 1510 } 1511 1512 /* 1513 * Enable link attention interrupt 1514 */ 1515 emlxs_enable_latt(hba); 1516 1517 /* Wait for link to come up */ 1518 i = cfg[CFG_LINKUP_DELAY].current; 1519 while (i && (hba->state < FC_LINK_UP)) { 1520 /* Check for hardware error */ 1521 if (hba->state == FC_ERROR) { 1522 EMLXS_MSGF(EMLXS_CONTEXT, 1523 &emlxs_init_failed_msg, 1524 "Adapter error."); 1525 1526 mbq = NULL; 1527 rval = EIO; 1528 goto failed; 1529 } 1530 1531 DELAYMS(1000); 1532 i--; 1533 } 1534 } else { 1535 EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST); 1536 } 1537 1538 /* 1539 * The leadvile driver will now handle the FLOGI at the driver level 1540 */ 1541 1542 return (0); 1543 1544 failed: 1545 1546 EMLXS_STATE_CHANGE(hba, FC_ERROR); 1547 1548 if (hba->intr_flags & EMLXS_MSI_ADDED) { 1549 (void) EMLXS_INTR_REMOVE(hba); 1550 } 1551 1552 if (mp) { 1553 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 1554 mp = NULL; 1555 } 1556 1557 if (mp1) { 1558 emlxs_mem_put(hba, MEM_BUF, (void *)mp1); 1559 mp1 = NULL; 1560 } 1561 1562 (void) emlxs_mem_free_buffer(hba); 1563 1564 if (mbq) { 1565 (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); 1566 mbq = NULL; 1567 mb = NULL; 1568 } 1569 1570 if (rval == 0) { 1571 rval = EIO; 1572 } 1573 1574 return (rval); 1575 1576 } /* emlxs_sli3_online() */ 1577 1578 1579 static void 1580 emlxs_sli3_offline(emlxs_hba_t *hba) 1581 { 1582 /* Reverse emlxs_sli3_online */ 1583 1584 /* Kill the adapter */ 1585 emlxs_sli3_hba_kill(hba); 1586 1587 /* Free driver shared memory */ 1588 (void) emlxs_mem_free_buffer(hba); 1589 1590 } /* emlxs_sli3_offline() */ 1591 1592 1593 static int 1594 emlxs_sli3_map_hdw(emlxs_hba_t *hba) 1595 { 1596 emlxs_port_t *port = &PPORT; 1597 dev_info_t *dip; 1598 ddi_device_acc_attr_t dev_attr; 1599 int status; 1600 1601 dip = (dev_info_t *)hba->dip; 1602 dev_attr = emlxs_dev_acc_attr; 1603 1604 if (hba->bus_type == SBUS_FC) { 1605 1606 if (hba->sli.sli3.slim_acc_handle == 0) { 1607 status = ddi_regs_map_setup(dip, 1608 SBUS_DFLY_SLIM_RINDEX, 1609 (caddr_t *)&hba->sli.sli3.slim_addr, 1610 0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle); 1611 if (status != DDI_SUCCESS) { 1612 EMLXS_MSGF(EMLXS_CONTEXT, 1613 &emlxs_attach_failed_msg, 1614 "(SBUS) ddi_regs_map_setup SLIM failed. " 1615 "status=%x", status); 1616 goto failed; 1617 } 1618 } 1619 if (hba->sli.sli3.csr_acc_handle == 0) { 1620 status = ddi_regs_map_setup(dip, 1621 SBUS_DFLY_CSR_RINDEX, 1622 (caddr_t *)&hba->sli.sli3.csr_addr, 1623 0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle); 1624 if (status != DDI_SUCCESS) { 1625 EMLXS_MSGF(EMLXS_CONTEXT, 1626 &emlxs_attach_failed_msg, 1627 "(SBUS) ddi_regs_map_setup DFLY CSR " 1628 "failed. status=%x", status); 1629 goto failed; 1630 } 1631 } 1632 if (hba->sli.sli3.sbus_flash_acc_handle == 0) { 1633 status = ddi_regs_map_setup(dip, SBUS_FLASH_RDWR, 1634 (caddr_t *)&hba->sli.sli3.sbus_flash_addr, 0, 0, 1635 &dev_attr, &hba->sli.sli3.sbus_flash_acc_handle); 1636 if (status != DDI_SUCCESS) { 1637 EMLXS_MSGF(EMLXS_CONTEXT, 1638 &emlxs_attach_failed_msg, 1639 "(SBUS) ddi_regs_map_setup Fcode Flash " 1640 "failed. status=%x", status); 1641 goto failed; 1642 } 1643 } 1644 if (hba->sli.sli3.sbus_core_acc_handle == 0) { 1645 status = ddi_regs_map_setup(dip, SBUS_TITAN_CORE_RINDEX, 1646 (caddr_t *)&hba->sli.sli3.sbus_core_addr, 0, 0, 1647 &dev_attr, &hba->sli.sli3.sbus_core_acc_handle); 1648 if (status != DDI_SUCCESS) { 1649 EMLXS_MSGF(EMLXS_CONTEXT, 1650 &emlxs_attach_failed_msg, 1651 "(SBUS) ddi_regs_map_setup TITAN CORE " 1652 "failed. status=%x", status); 1653 goto failed; 1654 } 1655 } 1656 1657 if (hba->sli.sli3.sbus_csr_handle == 0) { 1658 status = ddi_regs_map_setup(dip, SBUS_TITAN_CSR_RINDEX, 1659 (caddr_t *)&hba->sli.sli3.sbus_csr_addr, 1660 0, 0, &dev_attr, &hba->sli.sli3.sbus_csr_handle); 1661 if (status != DDI_SUCCESS) { 1662 EMLXS_MSGF(EMLXS_CONTEXT, 1663 &emlxs_attach_failed_msg, 1664 "(SBUS) ddi_regs_map_setup TITAN CSR " 1665 "failed. status=%x", status); 1666 goto failed; 1667 } 1668 } 1669 } else { /* ****** PCI ****** */ 1670 1671 if (hba->sli.sli3.slim_acc_handle == 0) { 1672 status = ddi_regs_map_setup(dip, PCI_SLIM_RINDEX, 1673 (caddr_t *)&hba->sli.sli3.slim_addr, 1674 0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle); 1675 if (status != DDI_SUCCESS) { 1676 EMLXS_MSGF(EMLXS_CONTEXT, 1677 &emlxs_attach_failed_msg, 1678 "(PCI) ddi_regs_map_setup SLIM failed. " 1679 "stat=%d mem=%p attr=%p hdl=%p", 1680 status, &hba->sli.sli3.slim_addr, &dev_attr, 1681 &hba->sli.sli3.slim_acc_handle); 1682 goto failed; 1683 } 1684 } 1685 1686 /* 1687 * Map in control registers, using memory-mapped version of 1688 * the registers rather than the I/O space-mapped registers. 1689 */ 1690 if (hba->sli.sli3.csr_acc_handle == 0) { 1691 status = ddi_regs_map_setup(dip, PCI_CSR_RINDEX, 1692 (caddr_t *)&hba->sli.sli3.csr_addr, 1693 0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle); 1694 if (status != DDI_SUCCESS) { 1695 EMLXS_MSGF(EMLXS_CONTEXT, 1696 &emlxs_attach_failed_msg, 1697 "ddi_regs_map_setup CSR failed. status=%x", 1698 status); 1699 goto failed; 1700 } 1701 } 1702 } 1703 1704 if (hba->sli.sli3.slim2.virt == 0) { 1705 MBUF_INFO *buf_info; 1706 MBUF_INFO bufinfo; 1707 1708 buf_info = &bufinfo; 1709 1710 bzero(buf_info, sizeof (MBUF_INFO)); 1711 buf_info->size = SLI_SLIM2_SIZE; 1712 buf_info->flags = 1713 FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; 1714 buf_info->align = ddi_ptob(dip, 1L); 1715 1716 (void) emlxs_mem_alloc(hba, buf_info); 1717 1718 if (buf_info->virt == NULL) { 1719 goto failed; 1720 } 1721 1722 hba->sli.sli3.slim2.virt = buf_info->virt; 1723 hba->sli.sli3.slim2.phys = buf_info->phys; 1724 hba->sli.sli3.slim2.size = SLI_SLIM2_SIZE; 1725 hba->sli.sli3.slim2.data_handle = buf_info->data_handle; 1726 hba->sli.sli3.slim2.dma_handle = buf_info->dma_handle; 1727 bzero((char *)hba->sli.sli3.slim2.virt, SLI_SLIM2_SIZE); 1728 } 1729 1730 /* offset from beginning of register space */ 1731 hba->sli.sli3.ha_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1732 (sizeof (uint32_t) * HA_REG_OFFSET)); 1733 hba->sli.sli3.ca_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1734 (sizeof (uint32_t) * CA_REG_OFFSET)); 1735 hba->sli.sli3.hs_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1736 (sizeof (uint32_t) * HS_REG_OFFSET)); 1737 hba->sli.sli3.hc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1738 (sizeof (uint32_t) * HC_REG_OFFSET)); 1739 hba->sli.sli3.bc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1740 (sizeof (uint32_t) * BC_REG_OFFSET)); 1741 1742 if (hba->bus_type == SBUS_FC) { 1743 /* offset from beginning of register space */ 1744 /* for TITAN registers */ 1745 hba->sli.sli3.shc_reg_addr = 1746 (uint32_t *)(hba->sli.sli3.sbus_csr_addr + 1747 (sizeof (uint32_t) * SBUS_CTRL_REG_OFFSET)); 1748 hba->sli.sli3.shs_reg_addr = 1749 (uint32_t *)(hba->sli.sli3.sbus_csr_addr + 1750 (sizeof (uint32_t) * SBUS_STAT_REG_OFFSET)); 1751 hba->sli.sli3.shu_reg_addr = 1752 (uint32_t *)(hba->sli.sli3.sbus_csr_addr + 1753 (sizeof (uint32_t) * SBUS_UPDATE_REG_OFFSET)); 1754 } 1755 hba->chan_count = MAX_RINGS; 1756 1757 return (0); 1758 1759 failed: 1760 1761 emlxs_sli3_unmap_hdw(hba); 1762 return (ENOMEM); 1763 1764 } /* emlxs_sli3_map_hdw() */ 1765 1766 1767 static void 1768 emlxs_sli3_unmap_hdw(emlxs_hba_t *hba) 1769 { 1770 MBUF_INFO bufinfo; 1771 MBUF_INFO *buf_info = &bufinfo; 1772 1773 if (hba->sli.sli3.csr_acc_handle) { 1774 ddi_regs_map_free(&hba->sli.sli3.csr_acc_handle); 1775 hba->sli.sli3.csr_acc_handle = 0; 1776 } 1777 1778 if (hba->sli.sli3.slim_acc_handle) { 1779 ddi_regs_map_free(&hba->sli.sli3.slim_acc_handle); 1780 hba->sli.sli3.slim_acc_handle = 0; 1781 } 1782 1783 if (hba->sli.sli3.sbus_flash_acc_handle) { 1784 ddi_regs_map_free(&hba->sli.sli3.sbus_flash_acc_handle); 1785 hba->sli.sli3.sbus_flash_acc_handle = 0; 1786 } 1787 1788 if (hba->sli.sli3.sbus_core_acc_handle) { 1789 ddi_regs_map_free(&hba->sli.sli3.sbus_core_acc_handle); 1790 hba->sli.sli3.sbus_core_acc_handle = 0; 1791 } 1792 1793 if (hba->sli.sli3.sbus_csr_handle) { 1794 ddi_regs_map_free(&hba->sli.sli3.sbus_csr_handle); 1795 hba->sli.sli3.sbus_csr_handle = 0; 1796 } 1797 1798 if (hba->sli.sli3.slim2.virt) { 1799 bzero(buf_info, sizeof (MBUF_INFO)); 1800 1801 if (hba->sli.sli3.slim2.phys) { 1802 buf_info->phys = hba->sli.sli3.slim2.phys; 1803 buf_info->data_handle = hba->sli.sli3.slim2.data_handle; 1804 buf_info->dma_handle = hba->sli.sli3.slim2.dma_handle; 1805 buf_info->flags = FC_MBUF_DMA; 1806 } 1807 1808 buf_info->virt = hba->sli.sli3.slim2.virt; 1809 buf_info->size = hba->sli.sli3.slim2.size; 1810 emlxs_mem_free(hba, buf_info); 1811 1812 hba->sli.sli3.slim2.virt = NULL; 1813 } 1814 1815 1816 return; 1817 1818 } /* emlxs_sli3_unmap_hdw() */ 1819 1820 1821 static uint32_t 1822 emlxs_sli3_hba_init(emlxs_hba_t *hba) 1823 { 1824 emlxs_port_t *port = &PPORT; 1825 emlxs_port_t *vport; 1826 emlxs_config_t *cfg; 1827 uint16_t i; 1828 1829 cfg = &CFG; 1830 i = 0; 1831 1832 /* Restart the adapter */ 1833 if (emlxs_sli3_hba_reset(hba, 1, 0, 0)) { 1834 return (1); 1835 } 1836 1837 hba->channel_fcp = FC_FCP_RING; 1838 hba->channel_els = FC_ELS_RING; 1839 hba->channel_ip = FC_IP_RING; 1840 hba->channel_ct = FC_CT_RING; 1841 hba->chan_count = MAX_RINGS; 1842 hba->sli.sli3.ring_count = MAX_RINGS; 1843 1844 /* 1845 * WARNING: There is a max of 6 ring masks allowed 1846 */ 1847 /* RING 0 - FCP */ 1848 if (hba->tgt_mode) { 1849 hba->sli.sli3.ring_masks[FC_FCP_RING] = 1; 1850 hba->sli.sli3.ring_rval[i] = FC_FCP_CMND; 1851 hba->sli.sli3.ring_rmask[i] = 0; 1852 hba->sli.sli3.ring_tval[i] = FC_FCP_DATA; 1853 hba->sli.sli3.ring_tmask[i++] = 0xFF; 1854 } else { 1855 hba->sli.sli3.ring_masks[FC_FCP_RING] = 0; 1856 } 1857 1858 hba->sli.sli3.ring[FC_FCP_RING].fc_numCiocb = SLIM_IOCB_CMD_R0_ENTRIES; 1859 hba->sli.sli3.ring[FC_FCP_RING].fc_numRiocb = SLIM_IOCB_RSP_R0_ENTRIES; 1860 1861 /* RING 1 - IP */ 1862 if (cfg[CFG_NETWORK_ON].current) { 1863 hba->sli.sli3.ring_masks[FC_IP_RING] = 1; 1864 hba->sli.sli3.ring_rval[i] = FC_UNSOL_DATA; /* Unsol Data */ 1865 hba->sli.sli3.ring_rmask[i] = 0xFF; 1866 hba->sli.sli3.ring_tval[i] = FC_LLC_SNAP; /* LLC/SNAP */ 1867 hba->sli.sli3.ring_tmask[i++] = 0xFF; 1868 } else { 1869 hba->sli.sli3.ring_masks[FC_IP_RING] = 0; 1870 } 1871 1872 hba->sli.sli3.ring[FC_IP_RING].fc_numCiocb = SLIM_IOCB_CMD_R1_ENTRIES; 1873 hba->sli.sli3.ring[FC_IP_RING].fc_numRiocb = SLIM_IOCB_RSP_R1_ENTRIES; 1874 1875 /* RING 2 - ELS */ 1876 hba->sli.sli3.ring_masks[FC_ELS_RING] = 1; 1877 hba->sli.sli3.ring_rval[i] = FC_ELS_REQ; /* ELS request/rsp */ 1878 hba->sli.sli3.ring_rmask[i] = 0xFE; 1879 hba->sli.sli3.ring_tval[i] = FC_ELS_DATA; /* ELS */ 1880 hba->sli.sli3.ring_tmask[i++] = 0xFF; 1881 1882 hba->sli.sli3.ring[FC_ELS_RING].fc_numCiocb = SLIM_IOCB_CMD_R2_ENTRIES; 1883 hba->sli.sli3.ring[FC_ELS_RING].fc_numRiocb = SLIM_IOCB_RSP_R2_ENTRIES; 1884 1885 /* RING 3 - CT */ 1886 hba->sli.sli3.ring_masks[FC_CT_RING] = 1; 1887 hba->sli.sli3.ring_rval[i] = FC_UNSOL_CTL; /* CT request/rsp */ 1888 hba->sli.sli3.ring_rmask[i] = 0xFE; 1889 hba->sli.sli3.ring_tval[i] = FC_CT_TYPE; /* CT */ 1890 hba->sli.sli3.ring_tmask[i++] = 0xFF; 1891 1892 hba->sli.sli3.ring[FC_CT_RING].fc_numCiocb = SLIM_IOCB_CMD_R3_ENTRIES; 1893 hba->sli.sli3.ring[FC_CT_RING].fc_numRiocb = SLIM_IOCB_RSP_R3_ENTRIES; 1894 1895 if (i > 6) { 1896 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 1897 "emlxs_hba_init: Too many ring masks defined. cnt=%d", i); 1898 return (1); 1899 } 1900 1901 /* Initialize all the port objects */ 1902 hba->vpi_base = 0; 1903 hba->vpi_max = 0; 1904 for (i = 0; i < MAX_VPORTS; i++) { 1905 vport = &VPORT(i); 1906 vport->hba = hba; 1907 vport->vpi = i; 1908 vport->VPIobj.index = i; 1909 vport->VPIobj.VPI = i; 1910 vport->VPIobj.port = vport; 1911 vport->VPIobj.state = VPI_STATE_OFFLINE; 1912 } 1913 1914 /* 1915 * Initialize the max_node count to a default value if needed 1916 * This determines how many node objects we preallocate in the pool 1917 * The actual max_nodes will be set later based on adapter info 1918 */ 1919 if (hba->max_nodes == 0) { 1920 if (cfg[CFG_NUM_NODES].current > 0) { 1921 hba->max_nodes = cfg[CFG_NUM_NODES].current; 1922 } else if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 1923 hba->max_nodes = 4096; 1924 } else { 1925 hba->max_nodes = 512; 1926 } 1927 } 1928 1929 return (0); 1930 1931 } /* emlxs_sli3_hba_init() */ 1932 1933 1934 /* 1935 * 0: quiesce indicates the call is not from quiesce routine. 1936 * 1: quiesce indicates the call is from quiesce routine. 1937 */ 1938 static uint32_t 1939 emlxs_sli3_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post, 1940 uint32_t quiesce) 1941 { 1942 emlxs_port_t *port = &PPORT; 1943 MAILBOX *swpmb; 1944 MAILBOX *mb; 1945 uint32_t word0; 1946 uint16_t cfg_value; 1947 uint32_t status; 1948 uint32_t status1; 1949 uint32_t status2; 1950 uint32_t i; 1951 uint32_t ready; 1952 emlxs_port_t *vport; 1953 RING *rp; 1954 emlxs_config_t *cfg = &CFG; 1955 1956 i = 0; 1957 1958 if (!cfg[CFG_RESET_ENABLE].current) { 1959 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 1960 "Adapter reset disabled."); 1961 EMLXS_STATE_CHANGE(hba, FC_ERROR); 1962 1963 return (1); 1964 } 1965 1966 /* Kill the adapter first */ 1967 if (quiesce == 0) { 1968 emlxs_sli3_hba_kill(hba); 1969 } else { 1970 emlxs_sli3_hba_kill4quiesce(hba); 1971 } 1972 1973 if (restart) { 1974 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1975 "Restarting."); 1976 EMLXS_STATE_CHANGE(hba, FC_INIT_START); 1977 1978 ready = (HS_FFRDY | HS_MBRDY); 1979 } else { 1980 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1981 "Resetting."); 1982 EMLXS_STATE_CHANGE(hba, FC_WARM_START); 1983 1984 ready = HS_MBRDY; 1985 } 1986 1987 hba->flag &= ~(FC_SLIM2_MODE | FC_HARDWARE_ERROR); 1988 1989 mb = FC_SLIM1_MAILBOX(hba); 1990 swpmb = (MAILBOX *)&word0; 1991 1992 reset: 1993 1994 /* Save reset time */ 1995 HBASTATS.ResetTime = hba->timer_tics; 1996 1997 if (restart) { 1998 /* First put restart command in mailbox */ 1999 word0 = 0; 2000 swpmb->mbxCommand = MBX_RESTART; 2001 swpmb->mbxHc = 1; 2002 WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb), word0); 2003 2004 /* Only skip post after emlxs_sli3_online is completed */ 2005 if (skip_post) { 2006 WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1), 2007 1); 2008 } else { 2009 WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1), 2010 0); 2011 } 2012 2013 } 2014 2015 /* 2016 * Turn off SERR, PERR in PCI cmd register 2017 */ 2018 cfg_value = ddi_get16(hba->pci_acc_handle, 2019 (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER)); 2020 2021 ddi_put16(hba->pci_acc_handle, 2022 (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 2023 (uint16_t)(cfg_value & ~(CMD_PARITY_CHK | CMD_SERR_ENBL))); 2024 2025 hba->sli.sli3.hc_copy = HC_INITFF; 2026 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 2027 2028 /* Wait 1 msec before restoring PCI config */ 2029 DELAYMS(1); 2030 2031 /* Restore PCI cmd register */ 2032 ddi_put16(hba->pci_acc_handle, 2033 (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 2034 (uint16_t)cfg_value); 2035 2036 /* Wait 3 seconds before checking */ 2037 DELAYMS(3000); 2038 i += 3; 2039 2040 /* Wait for reset completion */ 2041 while (i < 30) { 2042 /* Check status register to see what current state is */ 2043 status = READ_CSR_REG(hba, FC_HS_REG(hba)); 2044 2045 /* Check to see if any errors occurred during init */ 2046 if (status & HS_FFERM) { 2047 status1 = READ_SLIM_ADDR(hba, ((volatile uint8_t *) 2048 hba->sli.sli3.slim_addr + 0xa8)); 2049 status2 = READ_SLIM_ADDR(hba, ((volatile uint8_t *) 2050 hba->sli.sli3.slim_addr + 0xac)); 2051 2052 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 2053 "HS_FFERM: status=0x%x status1=0x%x status2=0x%x", 2054 status, status1, status2); 2055 2056 EMLXS_STATE_CHANGE(hba, FC_ERROR); 2057 return (1); 2058 } 2059 2060 if ((status & ready) == ready) { 2061 /* Reset Done !! */ 2062 goto done; 2063 } 2064 2065 /* 2066 * Check every 1 second for 15 seconds, then reset board 2067 * again (w/post), then check every 1 second for 15 * seconds. 2068 */ 2069 DELAYMS(1000); 2070 i++; 2071 2072 /* Reset again (w/post) at 15 seconds */ 2073 if (i == 15) { 2074 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2075 "Reset failed. Retrying..."); 2076 2077 goto reset; 2078 } 2079 } 2080 2081 #ifdef FMA_SUPPORT 2082 reset_fail: 2083 #endif /* FMA_SUPPORT */ 2084 2085 /* Timeout occurred */ 2086 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 2087 "Timeout: status=0x%x", status); 2088 EMLXS_STATE_CHANGE(hba, FC_ERROR); 2089 2090 /* Log a dump event */ 2091 emlxs_log_dump_event(port, NULL, 0); 2092 2093 return (1); 2094 2095 done: 2096 2097 /* Initialize hc_copy */ 2098 hba->sli.sli3.hc_copy = READ_CSR_REG(hba, FC_HC_REG(hba)); 2099 2100 #ifdef FMA_SUPPORT 2101 /* Access handle validation */ 2102 if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 2103 != DDI_FM_OK) || 2104 (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 2105 != DDI_FM_OK) || 2106 (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle) 2107 != DDI_FM_OK)) { 2108 EMLXS_MSGF(EMLXS_CONTEXT, 2109 &emlxs_invalid_access_handle_msg, NULL); 2110 goto reset_fail; 2111 } 2112 #endif /* FMA_SUPPORT */ 2113 2114 /* Reset the hba structure */ 2115 hba->flag &= FC_RESET_MASK; 2116 hba->channel_tx_count = 0; 2117 hba->io_count = 0; 2118 hba->iodone_count = 0; 2119 hba->topology = 0; 2120 hba->linkspeed = 0; 2121 hba->heartbeat_active = 0; 2122 hba->discovery_timer = 0; 2123 hba->linkup_timer = 0; 2124 hba->loopback_tics = 0; 2125 2126 2127 /* Reset the ring objects */ 2128 for (i = 0; i < MAX_RINGS; i++) { 2129 rp = &hba->sli.sli3.ring[i]; 2130 rp->fc_mpon = 0; 2131 rp->fc_mpoff = 0; 2132 } 2133 2134 /* Reset the port objects */ 2135 for (i = 0; i < MAX_VPORTS; i++) { 2136 vport = &VPORT(i); 2137 2138 vport->flag &= EMLXS_PORT_RESET_MASK; 2139 vport->did = 0; 2140 vport->prev_did = 0; 2141 vport->lip_type = 0; 2142 bzero(&vport->fabric_sparam, sizeof (SERV_PARM)); 2143 bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM)); 2144 2145 bzero((caddr_t)&vport->node_base, sizeof (NODELIST)); 2146 vport->node_base.nlp_Rpi = 0; 2147 vport->node_base.nlp_DID = 0xffffff; 2148 vport->node_base.nlp_list_next = NULL; 2149 vport->node_base.nlp_list_prev = NULL; 2150 vport->node_base.nlp_active = 1; 2151 vport->node_count = 0; 2152 2153 if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) { 2154 vport->ub_count = EMLXS_UB_TOKEN_OFFSET; 2155 } 2156 } 2157 2158 return (0); 2159 2160 } /* emlxs_sli3_hba_reset */ 2161 2162 2163 #define BPL_CMD 0 2164 #define BPL_RESP 1 2165 #define BPL_DATA 2 2166 2167 static ULP_BDE64 * 2168 emlxs_pkt_to_bpl(ULP_BDE64 *bpl, fc_packet_t *pkt, uint32_t bpl_type, 2169 uint8_t bdeFlags) 2170 { 2171 ddi_dma_cookie_t *cp; 2172 uint_t i; 2173 int32_t size; 2174 uint_t cookie_cnt; 2175 2176 #if (EMLXS_MODREV >= EMLXS_MODREV3) 2177 switch (bpl_type) { 2178 case BPL_CMD: 2179 cp = pkt->pkt_cmd_cookie; 2180 cookie_cnt = pkt->pkt_cmd_cookie_cnt; 2181 size = (int32_t)pkt->pkt_cmdlen; 2182 break; 2183 2184 case BPL_RESP: 2185 cp = pkt->pkt_resp_cookie; 2186 cookie_cnt = pkt->pkt_resp_cookie_cnt; 2187 size = (int32_t)pkt->pkt_rsplen; 2188 break; 2189 2190 2191 case BPL_DATA: 2192 cp = pkt->pkt_data_cookie; 2193 cookie_cnt = pkt->pkt_data_cookie_cnt; 2194 size = (int32_t)pkt->pkt_datalen; 2195 break; 2196 } 2197 2198 #else 2199 switch (bpl_type) { 2200 case BPL_CMD: 2201 cp = &pkt->pkt_cmd_cookie; 2202 cookie_cnt = 1; 2203 size = (int32_t)pkt->pkt_cmdlen; 2204 break; 2205 2206 case BPL_RESP: 2207 cp = &pkt->pkt_resp_cookie; 2208 cookie_cnt = 1; 2209 size = (int32_t)pkt->pkt_rsplen; 2210 break; 2211 2212 2213 case BPL_DATA: 2214 cp = &pkt->pkt_data_cookie; 2215 cookie_cnt = 1; 2216 size = (int32_t)pkt->pkt_datalen; 2217 break; 2218 } 2219 #endif /* >= EMLXS_MODREV3 */ 2220 2221 for (i = 0; i < cookie_cnt && size > 0; i++, cp++) { 2222 bpl->addrHigh = 2223 BE_SWAP32(PADDR_HI(cp->dmac_laddress)); 2224 bpl->addrLow = 2225 BE_SWAP32(PADDR_LO(cp->dmac_laddress)); 2226 bpl->tus.f.bdeSize = MIN(size, cp->dmac_size); 2227 bpl->tus.f.bdeFlags = bdeFlags; 2228 bpl->tus.w = BE_SWAP32(bpl->tus.w); 2229 2230 bpl++; 2231 size -= cp->dmac_size; 2232 } 2233 2234 return (bpl); 2235 2236 } /* emlxs_pkt_to_bpl */ 2237 2238 2239 static uint32_t 2240 emlxs_sli2_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 2241 { 2242 emlxs_hba_t *hba = HBA; 2243 fc_packet_t *pkt; 2244 MATCHMAP *bmp; 2245 ULP_BDE64 *bpl; 2246 uint64_t bp; 2247 uint8_t bdeFlag; 2248 IOCB *iocb; 2249 IOCBQ *iocbq; 2250 CHANNEL *cp; 2251 uint32_t cmd_cookie_cnt; 2252 uint32_t resp_cookie_cnt; 2253 uint32_t data_cookie_cnt; 2254 uint32_t cookie_cnt; 2255 2256 cp = sbp->channel; 2257 iocb = (IOCB *) & sbp->iocbq; 2258 pkt = PRIV2PKT(sbp); 2259 2260 #ifdef EMLXS_SPARC 2261 /* Use FCP MEM_BPL table to get BPL buffer */ 2262 bmp = hba->sli.sli3.fcp_bpl_table[sbp->iotag]; 2263 #else 2264 /* Use MEM_BPL pool to get BPL buffer */ 2265 bmp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BPL, 0); 2266 2267 #endif 2268 2269 if (!bmp) { 2270 return (1); 2271 } 2272 2273 sbp->bmp = bmp; 2274 bpl = (ULP_BDE64 *)bmp->virt; 2275 bp = bmp->phys; 2276 cookie_cnt = 0; 2277 2278 #if (EMLXS_MODREV >= EMLXS_MODREV3) 2279 cmd_cookie_cnt = pkt->pkt_cmd_cookie_cnt; 2280 resp_cookie_cnt = pkt->pkt_resp_cookie_cnt; 2281 data_cookie_cnt = pkt->pkt_data_cookie_cnt; 2282 #else 2283 cmd_cookie_cnt = 1; 2284 resp_cookie_cnt = 1; 2285 data_cookie_cnt = 1; 2286 #endif /* >= EMLXS_MODREV3 */ 2287 2288 iocbq = &sbp->iocbq; 2289 if (iocbq->flag & IOCB_FCP_CMD) 2290 goto fcpcmd; 2291 2292 switch (cp->channelno) { 2293 case FC_FCP_RING: 2294 fcpcmd: 2295 /* CMD payload */ 2296 bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0); 2297 cookie_cnt = cmd_cookie_cnt; 2298 2299 if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) { 2300 /* RSP payload */ 2301 bpl = 2302 emlxs_pkt_to_bpl(bpl, pkt, BPL_RESP, 2303 BUFF_USE_RCV); 2304 cookie_cnt += resp_cookie_cnt; 2305 2306 /* DATA payload */ 2307 if (pkt->pkt_datalen != 0) { 2308 bdeFlag = 2309 (pkt->pkt_tran_type == 2310 FC_PKT_FCP_READ) ? BUFF_USE_RCV : 0; 2311 bpl = 2312 emlxs_pkt_to_bpl(bpl, pkt, BPL_DATA, 2313 bdeFlag); 2314 cookie_cnt += data_cookie_cnt; 2315 } 2316 } 2317 /* 2318 * else 2319 * { 2320 * Target mode FCP status. Do nothing more. 2321 * } 2322 */ 2323 2324 break; 2325 2326 case FC_IP_RING: 2327 2328 /* CMD payload */ 2329 bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0); 2330 cookie_cnt = cmd_cookie_cnt; 2331 2332 break; 2333 2334 case FC_ELS_RING: 2335 2336 /* CMD payload */ 2337 bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0); 2338 cookie_cnt = cmd_cookie_cnt; 2339 2340 /* RSP payload */ 2341 if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) { 2342 bpl = 2343 emlxs_pkt_to_bpl(bpl, pkt, BPL_RESP, 2344 BUFF_USE_RCV); 2345 cookie_cnt += resp_cookie_cnt; 2346 } 2347 2348 break; 2349 2350 2351 case FC_CT_RING: 2352 2353 /* CMD payload */ 2354 bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0); 2355 cookie_cnt = cmd_cookie_cnt; 2356 2357 if ((pkt->pkt_tran_type != FC_PKT_OUTBOUND) || 2358 (pkt->pkt_cmd_fhdr.type == EMLXS_MENLO_TYPE)) { 2359 /* RSP payload */ 2360 bpl = 2361 emlxs_pkt_to_bpl(bpl, pkt, BPL_RESP, 2362 BUFF_USE_RCV); 2363 cookie_cnt += resp_cookie_cnt; 2364 } 2365 2366 break; 2367 2368 } 2369 2370 iocb->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BDL; 2371 iocb->un.genreq64.bdl.addrHigh = PADDR_HI(bp); 2372 iocb->un.genreq64.bdl.addrLow = PADDR_LO(bp); 2373 iocb->un.genreq64.bdl.bdeSize = cookie_cnt * sizeof (ULP_BDE64); 2374 2375 iocb->ULPBDECOUNT = 1; 2376 iocb->ULPLE = 1; 2377 2378 return (0); 2379 2380 } /* emlxs_sli2_bde_setup */ 2381 2382 2383 static uint32_t 2384 emlxs_sli3_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 2385 { 2386 ddi_dma_cookie_t *cp_cmd; 2387 ddi_dma_cookie_t *cp_resp; 2388 ddi_dma_cookie_t *cp_data; 2389 fc_packet_t *pkt; 2390 ULP_BDE64 *bde; 2391 int data_cookie_cnt; 2392 uint32_t i; 2393 IOCB *iocb; 2394 IOCBQ *iocbq; 2395 CHANNEL *cp; 2396 2397 cp = sbp->channel; 2398 iocb = (IOCB *) & sbp->iocbq; 2399 pkt = PRIV2PKT(sbp); 2400 #if (EMLXS_MODREV >= EMLXS_MODREV3) 2401 if ((pkt->pkt_cmd_cookie_cnt > 1) || 2402 (pkt->pkt_resp_cookie_cnt > 1) || 2403 ((pkt->pkt_cmd_cookie_cnt + pkt->pkt_resp_cookie_cnt + 2404 pkt->pkt_data_cookie_cnt) > SLI3_MAX_BDE)) { 2405 i = emlxs_sli2_bde_setup(port, sbp); 2406 return (i); 2407 } 2408 2409 #endif /* >= EMLXS_MODREV3 */ 2410 2411 #if (EMLXS_MODREV >= EMLXS_MODREV3) 2412 cp_cmd = pkt->pkt_cmd_cookie; 2413 cp_resp = pkt->pkt_resp_cookie; 2414 cp_data = pkt->pkt_data_cookie; 2415 data_cookie_cnt = pkt->pkt_data_cookie_cnt; 2416 #else 2417 cp_cmd = &pkt->pkt_cmd_cookie; 2418 cp_resp = &pkt->pkt_resp_cookie; 2419 cp_data = &pkt->pkt_data_cookie; 2420 data_cookie_cnt = 1; 2421 #endif /* >= EMLXS_MODREV3 */ 2422 2423 iocb->unsli3.ext_iocb.ebde_count = 0; 2424 2425 iocbq = &sbp->iocbq; 2426 if (iocbq->flag & IOCB_FCP_CMD) 2427 goto fcpcmd; 2428 2429 switch (cp->channelno) { 2430 case FC_FCP_RING: 2431 fcpcmd: 2432 /* CMD payload */ 2433 iocb->un.fcpi64.bdl.addrHigh = 2434 PADDR_HI(cp_cmd->dmac_laddress); 2435 iocb->un.fcpi64.bdl.addrLow = 2436 PADDR_LO(cp_cmd->dmac_laddress); 2437 iocb->un.fcpi64.bdl.bdeSize = pkt->pkt_cmdlen; 2438 iocb->un.fcpi64.bdl.bdeFlags = 0; 2439 2440 if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) { 2441 /* RSP payload */ 2442 iocb->unsli3.ext_iocb.ebde1.addrHigh = 2443 PADDR_HI(cp_resp->dmac_laddress); 2444 iocb->unsli3.ext_iocb.ebde1.addrLow = 2445 PADDR_LO(cp_resp->dmac_laddress); 2446 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = 2447 pkt->pkt_rsplen; 2448 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 0; 2449 iocb->unsli3.ext_iocb.ebde_count = 1; 2450 2451 /* DATA payload */ 2452 if (pkt->pkt_datalen != 0) { 2453 bde = 2454 (ULP_BDE64 *)&iocb->unsli3.ext_iocb. 2455 ebde2; 2456 for (i = 0; i < data_cookie_cnt; i++) { 2457 bde->addrHigh = 2458 PADDR_HI(cp_data-> 2459 dmac_laddress); 2460 bde->addrLow = 2461 PADDR_LO(cp_data-> 2462 dmac_laddress); 2463 bde->tus.f.bdeSize = 2464 cp_data->dmac_size; 2465 bde->tus.f.bdeFlags = 0; 2466 cp_data++; 2467 bde++; 2468 } 2469 iocb->unsli3.ext_iocb.ebde_count += 2470 data_cookie_cnt; 2471 } 2472 } 2473 /* 2474 * else 2475 * { 2476 * Target mode FCP status. Do nothing more. 2477 * } 2478 */ 2479 2480 break; 2481 2482 case FC_IP_RING: 2483 2484 /* CMD payload */ 2485 iocb->un.xseq64.bdl.addrHigh = 2486 PADDR_HI(cp_cmd->dmac_laddress); 2487 iocb->un.xseq64.bdl.addrLow = 2488 PADDR_LO(cp_cmd->dmac_laddress); 2489 iocb->un.xseq64.bdl.bdeSize = pkt->pkt_cmdlen; 2490 iocb->un.xseq64.bdl.bdeFlags = 0; 2491 2492 break; 2493 2494 case FC_ELS_RING: 2495 2496 /* CMD payload */ 2497 iocb->un.elsreq64.bdl.addrHigh = 2498 PADDR_HI(cp_cmd->dmac_laddress); 2499 iocb->un.elsreq64.bdl.addrLow = 2500 PADDR_LO(cp_cmd->dmac_laddress); 2501 iocb->un.elsreq64.bdl.bdeSize = pkt->pkt_cmdlen; 2502 iocb->un.elsreq64.bdl.bdeFlags = 0; 2503 2504 /* RSP payload */ 2505 if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) { 2506 iocb->unsli3.ext_iocb.ebde1.addrHigh = 2507 PADDR_HI(cp_resp->dmac_laddress); 2508 iocb->unsli3.ext_iocb.ebde1.addrLow = 2509 PADDR_LO(cp_resp->dmac_laddress); 2510 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = 2511 pkt->pkt_rsplen; 2512 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 2513 BUFF_USE_RCV; 2514 iocb->unsli3.ext_iocb.ebde_count = 1; 2515 } 2516 2517 break; 2518 2519 case FC_CT_RING: 2520 2521 /* CMD payload */ 2522 iocb->un.genreq64.bdl.addrHigh = 2523 PADDR_HI(cp_cmd->dmac_laddress); 2524 iocb->un.genreq64.bdl.addrLow = 2525 PADDR_LO(cp_cmd->dmac_laddress); 2526 iocb->un.genreq64.bdl.bdeSize = pkt->pkt_cmdlen; 2527 iocb->un.genreq64.bdl.bdeFlags = 0; 2528 2529 if ((pkt->pkt_tran_type != FC_PKT_OUTBOUND) || 2530 (pkt->pkt_cmd_fhdr.type == EMLXS_MENLO_TYPE)) { 2531 /* RSP payload */ 2532 iocb->unsli3.ext_iocb.ebde1.addrHigh = 2533 PADDR_HI(cp_resp->dmac_laddress); 2534 iocb->unsli3.ext_iocb.ebde1.addrLow = 2535 PADDR_LO(cp_resp->dmac_laddress); 2536 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = 2537 pkt->pkt_rsplen; 2538 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 2539 BUFF_USE_RCV; 2540 iocb->unsli3.ext_iocb.ebde_count = 1; 2541 } 2542 2543 break; 2544 } 2545 2546 iocb->ULPBDECOUNT = 0; 2547 iocb->ULPLE = 0; 2548 2549 return (0); 2550 2551 } /* emlxs_sli3_bde_setup */ 2552 2553 2554 /* Only used for FCP Data xfers */ 2555 #ifdef SFCT_SUPPORT 2556 /*ARGSUSED*/ 2557 static uint32_t 2558 emlxs_sli2_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 2559 { 2560 emlxs_hba_t *hba = HBA; 2561 scsi_task_t *fct_task; 2562 MATCHMAP *bmp; 2563 ULP_BDE64 *bpl; 2564 uint64_t bp; 2565 uint8_t bdeFlags; 2566 IOCB *iocb; 2567 uint32_t resid; 2568 uint32_t count; 2569 uint32_t size; 2570 uint32_t sgllen; 2571 struct stmf_sglist_ent *sgl; 2572 emlxs_fct_dmem_bctl_t *bctl; 2573 2574 2575 iocb = (IOCB *)&sbp->iocbq; 2576 sbp->bmp = NULL; 2577 2578 if (!sbp->fct_buf) { 2579 iocb->un.fcpt64.bdl.addrHigh = 0; 2580 iocb->un.fcpt64.bdl.addrLow = 0; 2581 iocb->un.fcpt64.bdl.bdeSize = 0; 2582 iocb->un.fcpt64.bdl.bdeFlags = 0; 2583 iocb->un.fcpt64.fcpt_Offset = 0; 2584 iocb->un.fcpt64.fcpt_Length = 0; 2585 iocb->ULPBDECOUNT = 0; 2586 iocb->ULPLE = 1; 2587 return (0); 2588 } 2589 #ifdef EMLXS_SPARC 2590 /* Use FCP MEM_BPL table to get BPL buffer */ 2591 bmp = hba->sli.sli3.fcp_bpl_table[sbp->iotag]; 2592 #else 2593 /* Use MEM_BPL pool to get BPL buffer */ 2594 bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL, 0); 2595 #endif /* EMLXS_SPARC */ 2596 2597 if (!bmp) { 2598 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2599 "emlxs_fct_sli2_bde_setup: Unable to BPL buffer. iotag=%x", 2600 sbp->iotag); 2601 2602 iocb->un.fcpt64.bdl.addrHigh = 0; 2603 iocb->un.fcpt64.bdl.addrLow = 0; 2604 iocb->un.fcpt64.bdl.bdeSize = 0; 2605 iocb->un.fcpt64.bdl.bdeFlags = 0; 2606 iocb->un.fcpt64.fcpt_Offset = 0; 2607 iocb->un.fcpt64.fcpt_Length = 0; 2608 iocb->ULPBDECOUNT = 0; 2609 iocb->ULPLE = 1; 2610 return (1); 2611 } 2612 2613 bpl = (ULP_BDE64 *)bmp->virt; 2614 bp = bmp->phys; 2615 2616 2617 fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific; 2618 2619 size = sbp->fct_buf->db_data_size; 2620 count = sbp->fct_buf->db_sglist_length; 2621 bctl = (emlxs_fct_dmem_bctl_t *)sbp->fct_buf->db_port_private; 2622 2623 bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0; 2624 sgl = sbp->fct_buf->db_sglist; 2625 resid = size; 2626 2627 /* Init the buffer list */ 2628 for (sgllen = 0; sgllen < count && resid > 0; sgllen++) { 2629 bpl->addrHigh = 2630 BE_SWAP32(PADDR_HI(bctl->bctl_dev_addr)); 2631 bpl->addrLow = 2632 BE_SWAP32(PADDR_LO(bctl->bctl_dev_addr)); 2633 bpl->tus.f.bdeSize = MIN(resid, sgl->seg_length); 2634 bpl->tus.f.bdeFlags = bdeFlags; 2635 bpl->tus.w = BE_SWAP32(bpl->tus.w); 2636 bpl++; 2637 2638 resid -= MIN(resid, sgl->seg_length); 2639 sgl++; 2640 } 2641 2642 /* Init the IOCB */ 2643 iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(bp); 2644 iocb->un.fcpt64.bdl.addrLow = PADDR_LO(bp); 2645 iocb->un.fcpt64.bdl.bdeSize = sgllen * sizeof (ULP_BDE64); 2646 iocb->un.fcpt64.bdl.bdeFlags = BUFF_TYPE_BDL; 2647 2648 iocb->un.fcpt64.fcpt_Length = 2649 (fct_task->task_flags & TF_WRITE_DATA) ? size : 0; 2650 iocb->un.fcpt64.fcpt_Offset = 0; 2651 2652 iocb->ULPBDECOUNT = 1; 2653 iocb->ULPLE = 1; 2654 sbp->bmp = bmp; 2655 2656 return (0); 2657 2658 } /* emlxs_sli2_fct_bde_setup */ 2659 #endif /* SFCT_SUPPORT */ 2660 2661 2662 #ifdef SFCT_SUPPORT 2663 /*ARGSUSED*/ 2664 static uint32_t 2665 emlxs_sli3_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 2666 { 2667 scsi_task_t *fct_task; 2668 ULP_BDE64 *bde; 2669 IOCB *iocb; 2670 uint32_t size; 2671 uint32_t count; 2672 uint32_t sgllen; 2673 int32_t resid; 2674 struct stmf_sglist_ent *sgl; 2675 uint32_t bdeFlags; 2676 emlxs_fct_dmem_bctl_t *bctl; 2677 2678 iocb = (IOCB *)&sbp->iocbq; 2679 2680 if (!sbp->fct_buf) { 2681 iocb->un.fcpt64.bdl.addrHigh = 0; 2682 iocb->un.fcpt64.bdl.addrLow = 0; 2683 iocb->un.fcpt64.bdl.bdeSize = 0; 2684 iocb->un.fcpt64.bdl.bdeFlags = 0; 2685 iocb->un.fcpt64.fcpt_Offset = 0; 2686 iocb->un.fcpt64.fcpt_Length = 0; 2687 iocb->ULPBDECOUNT = 0; 2688 iocb->ULPLE = 0; 2689 iocb->unsli3.ext_iocb.ebde_count = 0; 2690 return (0); 2691 } 2692 2693 fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific; 2694 2695 size = sbp->fct_buf->db_data_size; 2696 count = sbp->fct_buf->db_sglist_length; 2697 bctl = (emlxs_fct_dmem_bctl_t *)sbp->fct_buf->db_port_private; 2698 2699 bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0; 2700 sgl = sbp->fct_buf->db_sglist; 2701 resid = size; 2702 2703 /* Init first BDE */ 2704 iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(bctl->bctl_dev_addr); 2705 iocb->un.fcpt64.bdl.addrLow = PADDR_LO(bctl->bctl_dev_addr); 2706 iocb->un.fcpt64.bdl.bdeSize = MIN(resid, sgl->seg_length); 2707 iocb->un.fcpt64.bdl.bdeFlags = bdeFlags; 2708 resid -= MIN(resid, sgl->seg_length); 2709 sgl++; 2710 2711 /* Init remaining BDE's */ 2712 bde = (ULP_BDE64 *)&iocb->unsli3.ext_iocb.ebde1; 2713 for (sgllen = 1; sgllen < count && resid > 0; sgllen++) { 2714 bde->addrHigh = PADDR_HI(bctl->bctl_dev_addr); 2715 bde->addrLow = PADDR_LO(bctl->bctl_dev_addr); 2716 bde->tus.f.bdeSize = MIN(resid, sgl->seg_length); 2717 bde->tus.f.bdeFlags = bdeFlags; 2718 bde++; 2719 2720 resid -= MIN(resid, sgl->seg_length); 2721 sgl++; 2722 } 2723 2724 iocb->unsli3.ext_iocb.ebde_count = sgllen - 1; 2725 iocb->un.fcpt64.fcpt_Length = 2726 (fct_task->task_flags & TF_WRITE_DATA) ? size : 0; 2727 iocb->un.fcpt64.fcpt_Offset = 0; 2728 2729 iocb->ULPBDECOUNT = 0; 2730 iocb->ULPLE = 0; 2731 2732 return (0); 2733 2734 } /* emlxs_sli3_fct_bde_setup */ 2735 #endif /* SFCT_SUPPORT */ 2736 2737 2738 static void 2739 emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2740 { 2741 #ifdef FMA_SUPPORT 2742 emlxs_port_t *port = &PPORT; 2743 #endif /* FMA_SUPPORT */ 2744 PGP *pgp; 2745 emlxs_buf_t *sbp; 2746 SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; 2747 RING *rp; 2748 uint32_t nextIdx; 2749 uint32_t status; 2750 void *ioa2; 2751 off_t offset; 2752 uint32_t count = 0; 2753 uint32_t flag; 2754 uint32_t channelno; 2755 int32_t throttle; 2756 2757 channelno = cp->channelno; 2758 rp = (RING *)cp->iopath; 2759 2760 throttle = 0; 2761 2762 /* Check if FCP ring and adapter is not ready */ 2763 /* We may use any ring for FCP_CMD */ 2764 if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) { 2765 if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port || 2766 !(((emlxs_port_t *)iocbq->port)->tgt_mode)) { 2767 emlxs_tx_put(iocbq, 1); 2768 return; 2769 } 2770 } 2771 2772 /* Attempt to acquire CMD_RING lock */ 2773 if (mutex_tryenter(&EMLXS_CMD_RING_LOCK(channelno)) == 0) { 2774 /* Queue it for later */ 2775 if (iocbq) { 2776 if ((hba->io_count - 2777 hba->channel_tx_count) > 10) { 2778 emlxs_tx_put(iocbq, 1); 2779 return; 2780 } else { 2781 2782 /* 2783 * EMLXS_MSGF(EMLXS_CONTEXT, 2784 * &emlxs_ring_watchdog_msg, 2785 * "%s host=%d port=%d cnt=%d,%d RACE 2786 * CONDITION3 DETECTED.", 2787 * emlxs_ring_xlate(channelno), 2788 * rp->fc_cmdidx, rp->fc_port_cmdidx, 2789 * hba->channel_tx_count, 2790 * hba->io_count); 2791 */ 2792 mutex_enter(&EMLXS_CMD_RING_LOCK(channelno)); 2793 } 2794 } else { 2795 return; 2796 } 2797 } 2798 /* CMD_RING_LOCK acquired */ 2799 2800 /* Throttle check only applies to non special iocb */ 2801 if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) { 2802 /* Check if HBA is full */ 2803 throttle = hba->io_throttle - hba->io_active; 2804 if (throttle <= 0) { 2805 /* Hitting adapter throttle limit */ 2806 /* Queue it for later */ 2807 if (iocbq) { 2808 emlxs_tx_put(iocbq, 1); 2809 } 2810 2811 goto busy; 2812 } 2813 } 2814 2815 /* Read adapter's get index */ 2816 pgp = (PGP *) 2817 &((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port[channelno]; 2818 offset = 2819 (off_t)((uint64_t)((unsigned long)&(pgp->cmdGetInx)) - 2820 (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 2821 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 2822 DDI_DMA_SYNC_FORKERNEL); 2823 rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 2824 2825 /* Calculate the next put index */ 2826 nextIdx = 2827 (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1; 2828 2829 /* Check if ring is full */ 2830 if (nextIdx == rp->fc_port_cmdidx) { 2831 /* Try one more time */ 2832 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 2833 DDI_DMA_SYNC_FORKERNEL); 2834 rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 2835 2836 if (nextIdx == rp->fc_port_cmdidx) { 2837 /* Queue it for later */ 2838 if (iocbq) { 2839 emlxs_tx_put(iocbq, 1); 2840 } 2841 2842 goto busy; 2843 } 2844 } 2845 2846 /* 2847 * We have a command ring slot available 2848 * Make sure we have an iocb to send 2849 */ 2850 if (iocbq) { 2851 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2852 2853 /* Check if the ring already has iocb's waiting */ 2854 if (cp->nodeq.q_first != NULL) { 2855 /* Put the current iocbq on the tx queue */ 2856 emlxs_tx_put(iocbq, 0); 2857 2858 /* 2859 * Attempt to replace it with the next iocbq 2860 * in the tx queue 2861 */ 2862 iocbq = emlxs_tx_get(cp, 0); 2863 } 2864 2865 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2866 } else { 2867 /* Try to get the next iocb on the tx queue */ 2868 iocbq = emlxs_tx_get(cp, 1); 2869 } 2870 2871 sendit: 2872 count = 0; 2873 2874 /* Process each iocbq */ 2875 while (iocbq) { 2876 2877 sbp = iocbq->sbp; 2878 if (sbp && (sbp->pkt_flags & PACKET_DELAY_REQUIRED)) { 2879 /* 2880 * Update adapter if needed, since we are about to 2881 * delay here 2882 */ 2883 if (count) { 2884 count = 0; 2885 2886 /* Update the adapter's cmd put index */ 2887 if (hba->bus_type == SBUS_FC) { 2888 slim2p->mbx.us.s2.host[channelno]. 2889 cmdPutInx = 2890 BE_SWAP32(rp->fc_cmdidx); 2891 2892 /* DMA sync the index for the adapter */ 2893 offset = (off_t) 2894 ((uint64_t) 2895 ((unsigned long)&(slim2p->mbx.us. 2896 s2.host[channelno].cmdPutInx)) - 2897 (uint64_t)((unsigned long)slim2p)); 2898 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2. 2899 dma_handle, offset, 4, 2900 DDI_DMA_SYNC_FORDEV); 2901 } else { 2902 ioa2 = (void *) 2903 ((char *)hba->sli.sli3.slim_addr + 2904 hba->sli.sli3.hgp_ring_offset + 2905 ((channelno * 2) * 2906 sizeof (uint32_t))); 2907 WRITE_SLIM_ADDR(hba, 2908 (volatile uint32_t *)ioa2, 2909 rp->fc_cmdidx); 2910 } 2911 2912 status = (CA_R0ATT << (channelno * 4)); 2913 WRITE_CSR_REG(hba, FC_CA_REG(hba), 2914 (volatile uint32_t)status); 2915 2916 } 2917 /* Perform delay */ 2918 if ((channelno == FC_ELS_RING) && 2919 !(iocbq->flag & IOCB_FCP_CMD)) { 2920 drv_usecwait(100000); 2921 } else { 2922 drv_usecwait(20000); 2923 } 2924 } 2925 2926 /* 2927 * At this point, we have a command ring slot available 2928 * and an iocb to send 2929 */ 2930 flag = iocbq->flag; 2931 2932 /* Send the iocb */ 2933 emlxs_sli3_issue_iocb(hba, rp, iocbq); 2934 /* 2935 * After this, the sbp / iocb should not be 2936 * accessed in the xmit path. 2937 */ 2938 2939 count++; 2940 if (iocbq && (!(flag & IOCB_SPECIAL))) { 2941 /* Check if HBA is full */ 2942 throttle = hba->io_throttle - hba->io_active; 2943 if (throttle <= 0) { 2944 goto busy; 2945 } 2946 } 2947 2948 /* Calculate the next put index */ 2949 nextIdx = 2950 (rp->fc_cmdidx + 1 >= 2951 rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1; 2952 2953 /* Check if ring is full */ 2954 if (nextIdx == rp->fc_port_cmdidx) { 2955 /* Try one more time */ 2956 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 2957 offset, 4, DDI_DMA_SYNC_FORKERNEL); 2958 rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 2959 2960 if (nextIdx == rp->fc_port_cmdidx) { 2961 goto busy; 2962 } 2963 } 2964 2965 /* Get the next iocb from the tx queue if there is one */ 2966 iocbq = emlxs_tx_get(cp, 1); 2967 } 2968 2969 if (count) { 2970 /* Update the adapter's cmd put index */ 2971 if (hba->bus_type == SBUS_FC) { 2972 slim2p->mbx.us.s2.host[channelno]. 2973 cmdPutInx = BE_SWAP32(rp->fc_cmdidx); 2974 2975 /* DMA sync the index for the adapter */ 2976 offset = (off_t) 2977 ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2. 2978 host[channelno].cmdPutInx)) - 2979 (uint64_t)((unsigned long)slim2p)); 2980 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 2981 offset, 4, DDI_DMA_SYNC_FORDEV); 2982 } else { 2983 ioa2 = 2984 (void *)((char *)hba->sli.sli3.slim_addr + 2985 hba->sli.sli3.hgp_ring_offset + 2986 ((channelno * 2) * sizeof (uint32_t))); 2987 WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, 2988 rp->fc_cmdidx); 2989 } 2990 2991 status = (CA_R0ATT << (channelno * 4)); 2992 WRITE_CSR_REG(hba, FC_CA_REG(hba), 2993 (volatile uint32_t)status); 2994 2995 /* Check tx queue one more time before releasing */ 2996 if ((iocbq = emlxs_tx_get(cp, 1))) { 2997 /* 2998 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_watchdog_msg, 2999 * "%s host=%d port=%d RACE CONDITION1 3000 * DETECTED.", emlxs_ring_xlate(channelno), 3001 * rp->fc_cmdidx, rp->fc_port_cmdidx); 3002 */ 3003 goto sendit; 3004 } 3005 } 3006 3007 #ifdef FMA_SUPPORT 3008 /* Access handle validation */ 3009 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 3010 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 3011 #endif /* FMA_SUPPORT */ 3012 3013 mutex_exit(&EMLXS_CMD_RING_LOCK(channelno)); 3014 3015 return; 3016 3017 busy: 3018 3019 /* 3020 * Set ring to SET R0CE_REQ in Chip Att register. 3021 * Chip will tell us when an entry is freed. 3022 */ 3023 if (count) { 3024 /* Update the adapter's cmd put index */ 3025 if (hba->bus_type == SBUS_FC) { 3026 slim2p->mbx.us.s2.host[channelno].cmdPutInx = 3027 BE_SWAP32(rp->fc_cmdidx); 3028 3029 /* DMA sync the index for the adapter */ 3030 offset = (off_t) 3031 ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2. 3032 host[channelno].cmdPutInx)) - 3033 (uint64_t)((unsigned long)slim2p)); 3034 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 3035 offset, 4, DDI_DMA_SYNC_FORDEV); 3036 } else { 3037 ioa2 = 3038 (void *)((char *)hba->sli.sli3.slim_addr + 3039 hba->sli.sli3.hgp_ring_offset + 3040 ((channelno * 2) * sizeof (uint32_t))); 3041 WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, 3042 rp->fc_cmdidx); 3043 } 3044 } 3045 3046 status = ((CA_R0ATT | CA_R0CE_REQ) << (channelno * 4)); 3047 WRITE_CSR_REG(hba, FC_CA_REG(hba), (volatile uint32_t)status); 3048 3049 if (throttle <= 0) { 3050 HBASTATS.IocbThrottled++; 3051 } else { 3052 HBASTATS.IocbRingFull[channelno]++; 3053 } 3054 3055 #ifdef FMA_SUPPORT 3056 /* Access handle validation */ 3057 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 3058 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 3059 #endif /* FMA_SUPPORT */ 3060 3061 mutex_exit(&EMLXS_CMD_RING_LOCK(channelno)); 3062 3063 return; 3064 3065 } /* emlxs_sli3_issue_iocb_cmd() */ 3066 3067 3068 /* MBX_NOWAIT - returns MBX_BUSY or MBX_SUCCESS or MBX_HARDWARE_ERROR */ 3069 /* MBX_WAIT - returns MBX_TIMEOUT or mailbox_status */ 3070 /* MBX_SLEEP - returns MBX_TIMEOUT or mailbox_status */ 3071 /* MBX_POLL - returns MBX_TIMEOUT or mailbox_status */ 3072 3073 static uint32_t 3074 emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, 3075 uint32_t tmo) 3076 { 3077 emlxs_port_t *port; 3078 SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; 3079 MAILBOX *mbox; 3080 MAILBOX *mb; 3081 volatile uint32_t word0; 3082 volatile uint32_t ldata; 3083 uint32_t ha_copy; 3084 off_t offset; 3085 MATCHMAP *mbox_bp; 3086 uint32_t tmo_local; 3087 MAILBOX *swpmb; 3088 3089 if (!mbq->port) { 3090 mbq->port = &PPORT; 3091 } 3092 3093 port = (emlxs_port_t *)mbq->port; 3094 3095 mb = (MAILBOX *)mbq; 3096 swpmb = (MAILBOX *)&word0; 3097 3098 mb->mbxStatus = MBX_SUCCESS; 3099 3100 /* Check for minimum timeouts */ 3101 switch (mb->mbxCommand) { 3102 /* Mailbox commands that erase/write flash */ 3103 case MBX_DOWN_LOAD: 3104 case MBX_UPDATE_CFG: 3105 case MBX_LOAD_AREA: 3106 case MBX_LOAD_EXP_ROM: 3107 case MBX_WRITE_NV: 3108 case MBX_FLASH_WR_ULA: 3109 case MBX_DEL_LD_ENTRY: 3110 case MBX_LOAD_SM: 3111 if (tmo < 300) { 3112 tmo = 300; 3113 } 3114 break; 3115 3116 default: 3117 if (tmo < 30) { 3118 tmo = 30; 3119 } 3120 break; 3121 } 3122 3123 /* Convert tmo seconds to 10 millisecond tics */ 3124 tmo_local = tmo * 100; 3125 3126 /* Adjust wait flag */ 3127 if (flag != MBX_NOWAIT) { 3128 /* If interrupt is enabled, use sleep, otherwise poll */ 3129 if (hba->sli.sli3.hc_copy & HC_MBINT_ENA) { 3130 flag = MBX_SLEEP; 3131 } else { 3132 flag = MBX_POLL; 3133 } 3134 } 3135 3136 mutex_enter(&EMLXS_PORT_LOCK); 3137 3138 /* Check for hardware error */ 3139 if (hba->flag & FC_HARDWARE_ERROR) { 3140 mb->mbxStatus = (hba->flag & FC_OVERTEMP_EVENT) ? 3141 MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR; 3142 3143 mutex_exit(&EMLXS_PORT_LOCK); 3144 3145 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3146 "Hardware error reported. %s failed. status=%x mb=%p", 3147 emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb); 3148 3149 return (MBX_HARDWARE_ERROR); 3150 } 3151 3152 if (hba->mbox_queue_flag) { 3153 /* If we are not polling, then queue it for later */ 3154 if (flag == MBX_NOWAIT) { 3155 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3156 "Busy. %s: mb=%p NoWait.", 3157 emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3158 3159 emlxs_mb_put(hba, mbq); 3160 3161 HBASTATS.MboxBusy++; 3162 3163 mutex_exit(&EMLXS_PORT_LOCK); 3164 3165 return (MBX_BUSY); 3166 } 3167 3168 while (hba->mbox_queue_flag) { 3169 mutex_exit(&EMLXS_PORT_LOCK); 3170 3171 if (tmo_local-- == 0) { 3172 EMLXS_MSGF(EMLXS_CONTEXT, 3173 &emlxs_mbox_event_msg, 3174 "Timeout. %s: mb=%p tmo=%d Waiting.", 3175 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3176 tmo); 3177 3178 /* Non-lethalStatus mailbox timeout */ 3179 /* Does not indicate a hardware error */ 3180 mb->mbxStatus = MBX_TIMEOUT; 3181 return (MBX_TIMEOUT); 3182 } 3183 3184 DELAYMS(10); 3185 mutex_enter(&EMLXS_PORT_LOCK); 3186 } 3187 } 3188 3189 /* Initialize mailbox area */ 3190 emlxs_mb_init(hba, mbq, flag, tmo); 3191 3192 switch (flag) { 3193 case MBX_NOWAIT: 3194 3195 if (mb->mbxCommand != MBX_HEARTBEAT) { 3196 if (mb->mbxCommand != MBX_DOWN_LOAD && 3197 mb->mbxCommand != MBX_DUMP_MEMORY) { 3198 EMLXS_MSGF(EMLXS_CONTEXT, 3199 &emlxs_mbox_detail_msg, 3200 "Sending. %s: mb=%p NoWait.", 3201 emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3202 } 3203 } 3204 3205 break; 3206 3207 case MBX_SLEEP: 3208 if (mb->mbxCommand != MBX_DOWN_LOAD && 3209 mb->mbxCommand != MBX_DUMP_MEMORY) { 3210 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3211 "Sending. %s: mb=%p Sleep.", 3212 emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3213 } 3214 3215 break; 3216 3217 case MBX_POLL: 3218 if (mb->mbxCommand != MBX_DOWN_LOAD && 3219 mb->mbxCommand != MBX_DUMP_MEMORY) { 3220 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3221 "Sending. %s: mb=%p Polled.", 3222 emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3223 } 3224 break; 3225 } 3226 3227 mb->mbxOwner = OWN_CHIP; 3228 3229 /* Clear the attention bit */ 3230 WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT); 3231 3232 if (hba->flag & FC_SLIM2_MODE) { 3233 /* First copy command data */ 3234 mbox = FC_SLIM2_MAILBOX(hba); 3235 offset = 3236 (off_t)((uint64_t)((unsigned long)mbox) 3237 - (uint64_t)((unsigned long)slim2p)); 3238 3239 #ifdef MBOX_EXT_SUPPORT 3240 if (mbq->extbuf) { 3241 uint32_t *mbox_ext = 3242 (uint32_t *)((uint8_t *)mbox + 3243 MBOX_EXTENSION_OFFSET); 3244 off_t offset_ext = offset + MBOX_EXTENSION_OFFSET; 3245 3246 BE_SWAP32_BCOPY((uint8_t *)mbq->extbuf, 3247 (uint8_t *)mbox_ext, mbq->extsize); 3248 3249 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 3250 offset_ext, mbq->extsize, 3251 DDI_DMA_SYNC_FORDEV); 3252 } 3253 #endif /* MBOX_EXT_SUPPORT */ 3254 3255 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mbox, 3256 MAILBOX_CMD_BSIZE); 3257 3258 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 3259 MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV); 3260 } 3261 /* Check for config port command */ 3262 else if (mb->mbxCommand == MBX_CONFIG_PORT) { 3263 /* copy command data into host mbox for cmpl */ 3264 mbox = FC_SLIM2_MAILBOX(hba); 3265 offset = (off_t)((uint64_t)((unsigned long)mbox) 3266 - (uint64_t)((unsigned long)slim2p)); 3267 3268 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mbox, 3269 MAILBOX_CMD_BSIZE); 3270 3271 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 3272 MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV); 3273 3274 /* First copy command data */ 3275 mbox = FC_SLIM1_MAILBOX(hba); 3276 WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords, 3277 (MAILBOX_CMD_WSIZE - 1)); 3278 3279 /* copy over last word, with mbxOwner set */ 3280 ldata = *((volatile uint32_t *)mb); 3281 WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mbox), ldata); 3282 3283 /* switch over to host mailbox */ 3284 hba->flag |= FC_SLIM2_MODE; 3285 } else { /* SLIM 1 */ 3286 3287 mbox = FC_SLIM1_MAILBOX(hba); 3288 3289 #ifdef MBOX_EXT_SUPPORT 3290 if (mbq->extbuf) { 3291 uint32_t *mbox_ext = 3292 (uint32_t *)((uint8_t *)mbox + 3293 MBOX_EXTENSION_OFFSET); 3294 WRITE_SLIM_COPY(hba, (uint32_t *)mbq->extbuf, 3295 mbox_ext, (mbq->extsize / 4)); 3296 } 3297 #endif /* MBOX_EXT_SUPPORT */ 3298 3299 /* First copy command data */ 3300 WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords, 3301 (MAILBOX_CMD_WSIZE - 1)); 3302 3303 /* copy over last word, with mbxOwner set */ 3304 ldata = *((volatile uint32_t *)mb); 3305 WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mbox), ldata); 3306 } 3307 3308 /* Interrupt board to do it right away */ 3309 WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 3310 3311 mutex_exit(&EMLXS_PORT_LOCK); 3312 3313 #ifdef FMA_SUPPORT 3314 /* Access handle validation */ 3315 if ((emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 3316 != DDI_FM_OK) || 3317 (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle) 3318 != DDI_FM_OK)) { 3319 EMLXS_MSGF(EMLXS_CONTEXT, 3320 &emlxs_invalid_access_handle_msg, NULL); 3321 return (MBX_HARDWARE_ERROR); 3322 } 3323 #endif /* FMA_SUPPORT */ 3324 3325 switch (flag) { 3326 case MBX_NOWAIT: 3327 return (MBX_SUCCESS); 3328 3329 case MBX_SLEEP: 3330 3331 /* Wait for completion */ 3332 /* The driver clock is timing the mailbox. */ 3333 /* emlxs_mb_fini() will be called externally. */ 3334 3335 mutex_enter(&EMLXS_MBOX_LOCK); 3336 while (!(mbq->flag & MBQ_COMPLETED)) { 3337 cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK); 3338 } 3339 mutex_exit(&EMLXS_MBOX_LOCK); 3340 3341 if (mb->mbxStatus == MBX_TIMEOUT) { 3342 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg, 3343 "Timeout. %s: mb=%p tmo=%d. Sleep.", 3344 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo); 3345 } else { 3346 if (mb->mbxCommand != MBX_DOWN_LOAD && 3347 mb->mbxCommand != MBX_DUMP_MEMORY) { 3348 EMLXS_MSGF(EMLXS_CONTEXT, 3349 &emlxs_mbox_detail_msg, 3350 "Completed. %s: mb=%p status=%x Sleep.", 3351 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3352 mb->mbxStatus); 3353 } 3354 } 3355 3356 break; 3357 3358 case MBX_POLL: 3359 3360 /* Convert tmo seconds to 500 usec tics */ 3361 tmo_local = tmo * 2000; 3362 3363 if (hba->state >= FC_INIT_START) { 3364 ha_copy = 3365 READ_CSR_REG(hba, FC_HA_REG(hba)); 3366 3367 /* Wait for command to complete */ 3368 while (!(ha_copy & HA_MBATT) && 3369 !(mbq->flag & MBQ_COMPLETED)) { 3370 if (!hba->timer_id && (tmo_local-- == 0)) { 3371 /* self time */ 3372 EMLXS_MSGF(EMLXS_CONTEXT, 3373 &emlxs_mbox_timeout_msg, 3374 "%s: mb=%p Polled.", 3375 emlxs_mb_cmd_xlate(mb-> 3376 mbxCommand), mb); 3377 3378 hba->flag |= FC_MBOX_TIMEOUT; 3379 EMLXS_STATE_CHANGE(hba, FC_ERROR); 3380 emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 3381 3382 break; 3383 } 3384 3385 DELAYUS(500); 3386 ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba)); 3387 } 3388 3389 if (mb->mbxStatus == MBX_TIMEOUT) { 3390 EMLXS_MSGF(EMLXS_CONTEXT, 3391 &emlxs_mbox_event_msg, 3392 "Timeout. %s: mb=%p tmo=%d. Polled.", 3393 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3394 tmo); 3395 3396 break; 3397 } 3398 } 3399 3400 /* Get first word of mailbox */ 3401 if (hba->flag & FC_SLIM2_MODE) { 3402 mbox = FC_SLIM2_MAILBOX(hba); 3403 offset = (off_t)((uint64_t)((unsigned long)mbox) - 3404 (uint64_t)((unsigned long)slim2p)); 3405 3406 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 3407 offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 3408 word0 = *((volatile uint32_t *)mbox); 3409 word0 = BE_SWAP32(word0); 3410 } else { 3411 mbox = FC_SLIM1_MAILBOX(hba); 3412 word0 = 3413 READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); 3414 } 3415 3416 /* Wait for command to complete */ 3417 while ((swpmb->mbxOwner == OWN_CHIP) && 3418 !(mbq->flag & MBQ_COMPLETED)) { 3419 if (!hba->timer_id && (tmo_local-- == 0)) { 3420 /* self time */ 3421 EMLXS_MSGF(EMLXS_CONTEXT, 3422 &emlxs_mbox_timeout_msg, 3423 "%s: mb=%p Polled.", 3424 emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3425 3426 hba->flag |= FC_MBOX_TIMEOUT; 3427 EMLXS_STATE_CHANGE(hba, FC_ERROR); 3428 emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 3429 3430 break; 3431 } 3432 3433 DELAYUS(500); 3434 3435 /* Get first word of mailbox */ 3436 if (hba->flag & FC_SLIM2_MODE) { 3437 EMLXS_MPDATA_SYNC( 3438 hba->sli.sli3.slim2.dma_handle, offset, 3439 sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 3440 word0 = *((volatile uint32_t *)mbox); 3441 word0 = BE_SWAP32(word0); 3442 } else { 3443 word0 = 3444 READ_SLIM_ADDR(hba, 3445 ((volatile uint32_t *)mbox)); 3446 } 3447 3448 } /* while */ 3449 3450 if (mb->mbxStatus == MBX_TIMEOUT) { 3451 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg, 3452 "Timeout. %s: mb=%p tmo=%d. Polled.", 3453 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo); 3454 3455 break; 3456 } 3457 3458 /* copy results back to user */ 3459 if (hba->flag & FC_SLIM2_MODE) { 3460 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 3461 offset, MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL); 3462 3463 BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb, 3464 MAILBOX_CMD_BSIZE); 3465 } else { 3466 READ_SLIM_COPY(hba, (uint32_t *)mb, 3467 (uint32_t *)mbox, MAILBOX_CMD_WSIZE); 3468 } 3469 3470 #ifdef MBOX_EXT_SUPPORT 3471 if (mbq->extbuf) { 3472 uint32_t *mbox_ext = 3473 (uint32_t *)((uint8_t *)mbox + 3474 MBOX_EXTENSION_OFFSET); 3475 off_t offset_ext = offset + MBOX_EXTENSION_OFFSET; 3476 3477 if (hba->flag & FC_SLIM2_MODE) { 3478 EMLXS_MPDATA_SYNC( 3479 hba->sli.sli3.slim2.dma_handle, offset_ext, 3480 mbq->extsize, DDI_DMA_SYNC_FORKERNEL); 3481 3482 BE_SWAP32_BCOPY((uint8_t *)mbox_ext, 3483 (uint8_t *)mbq->extbuf, mbq->extsize); 3484 } else { 3485 READ_SLIM_COPY(hba, 3486 (uint32_t *)mbq->extbuf, mbox_ext, 3487 (mbq->extsize / 4)); 3488 } 3489 } 3490 #endif /* MBOX_EXT_SUPPORT */ 3491 3492 /* Sync the memory buffer */ 3493 if (mbq->bp) { 3494 mbox_bp = (MATCHMAP *)mbq->bp; 3495 EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, 3496 mbox_bp->size, DDI_DMA_SYNC_FORKERNEL); 3497 } 3498 3499 if (mb->mbxCommand != MBX_DOWN_LOAD && 3500 mb->mbxCommand != MBX_DUMP_MEMORY) { 3501 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3502 "Completed. %s: mb=%p status=%x Polled.", 3503 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3504 mb->mbxStatus); 3505 } 3506 3507 /* Process the result */ 3508 if (!(mbq->flag & MBQ_PASSTHRU)) { 3509 if (mbq->mbox_cmpl) { 3510 (void) (mbq->mbox_cmpl)(hba, mbq); 3511 } 3512 } 3513 3514 /* Clear the attention bit */ 3515 WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT); 3516 3517 /* Clean up the mailbox area */ 3518 emlxs_mb_fini(hba, NULL, mb->mbxStatus); 3519 3520 break; 3521 3522 } /* switch (flag) */ 3523 3524 return (mb->mbxStatus); 3525 3526 } /* emlxs_sli3_issue_mbox_cmd() */ 3527 3528 3529 #ifdef SFCT_SUPPORT 3530 static uint32_t 3531 emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, 3532 int channel) 3533 { 3534 emlxs_hba_t *hba = HBA; 3535 emlxs_config_t *cfg = &CFG; 3536 fct_cmd_t *fct_cmd; 3537 stmf_data_buf_t *dbuf; 3538 scsi_task_t *fct_task; 3539 uint32_t did; 3540 IOCBQ *iocbq; 3541 IOCB *iocb; 3542 uint32_t timeout; 3543 uint32_t iotag; 3544 emlxs_node_t *ndlp; 3545 CHANNEL *cp; 3546 3547 dbuf = cmd_sbp->fct_buf; 3548 fct_cmd = cmd_sbp->fct_cmd; 3549 fct_task = (scsi_task_t *)fct_cmd->cmd_specific; 3550 ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private; 3551 did = fct_cmd->cmd_rportid; 3552 3553 cp = (CHANNEL *)cmd_sbp->channel; 3554 3555 channel = channel; 3556 iocbq = &cmd_sbp->iocbq; 3557 iocb = &iocbq->iocb; 3558 3559 if (cfg[CFG_TIMEOUT_ENABLE].current) { 3560 timeout = 3561 ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov); 3562 } else { 3563 timeout = 0x80000000; 3564 } 3565 3566 #ifdef FCT_API_TRACE 3567 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3568 "emlxs_fct_send_fcp_data %p: flgs=%x ioflags=%x dl=%d,%d,%d,%d,%d", 3569 fct_cmd, dbuf->db_flags, ioflags, fct_task->task_cmd_xfer_length, 3570 fct_task->task_nbytes_transferred, dbuf->db_data_size, 3571 fct_task->task_expected_xfer_length, channel); 3572 #endif /* FCT_API_TRACE */ 3573 3574 3575 /* Get the iotag by registering the packet */ 3576 iotag = emlxs_register_pkt(cp, cmd_sbp); 3577 3578 if (!iotag) { 3579 /* No more command slots available, retry later */ 3580 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3581 "Adapter Busy. Unable to allocate iotag. did=0x%x", did); 3582 3583 return (IOERR_NO_RESOURCES); 3584 } 3585 3586 cmd_sbp->ticks = 3587 hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10); 3588 3589 /* Initalize iocbq */ 3590 iocbq->port = (void *)port; 3591 iocbq->node = (void *)ndlp; 3592 3593 3594 iocbq->channel = (void *)cmd_sbp->channel; 3595 3596 if (emlxs_fct_bde_setup(port, cmd_sbp)) { 3597 /* Unregister the packet */ 3598 (void) emlxs_unregister_pkt(cmd_sbp->channel, iotag, 0); 3599 3600 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3601 "Adapter Busy. Unable to setup buffer list. did=%x", did); 3602 3603 return (IOERR_INTERNAL_ERROR); 3604 } 3605 /* Point of no return */ 3606 3607 /* Initalize iocb */ 3608 iocb->ULPCONTEXT = (uint16_t)fct_cmd->cmd_rxid; 3609 iocb->ULPIOTAG = (uint16_t)iotag; 3610 iocb->ULPRSVDBYTE = ((timeout > 0xff) ? 0 : timeout); 3611 iocb->ULPOWNER = OWN_CHIP; 3612 iocb->ULPCLASS = cmd_sbp->class; 3613 3614 iocb->ULPPU = 1; /* Wd4 is relative offset */ 3615 iocb->un.fcpt64.fcpt_Offset = dbuf->db_relative_offset; 3616 3617 if (fct_task->task_flags & TF_WRITE_DATA) { 3618 iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX; 3619 } else { /* TF_READ_DATA */ 3620 3621 iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX; 3622 3623 if ((hba->sli_mode == EMLXS_HBA_SLI3_MODE) && 3624 (dbuf->db_data_size == 3625 fct_task->task_expected_xfer_length)) { 3626 iocb->ULPCT = 0x1; 3627 /* enable auto-rsp AP feature */ 3628 } 3629 } 3630 3631 return (IOERR_SUCCESS); 3632 3633 } /* emlxs_sli3_prep_fct_iocb() */ 3634 #endif /* SFCT_SUPPORT */ 3635 3636 /* ARGSUSED */ 3637 static uint32_t 3638 emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) 3639 { 3640 emlxs_hba_t *hba = HBA; 3641 fc_packet_t *pkt; 3642 CHANNEL *cp; 3643 IOCBQ *iocbq; 3644 IOCB *iocb; 3645 NODELIST *ndlp; 3646 uint16_t iotag; 3647 uint32_t did; 3648 3649 pkt = PRIV2PKT(sbp); 3650 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 3651 cp = &hba->chan[FC_FCP_RING]; 3652 3653 iocbq = &sbp->iocbq; 3654 iocb = &iocbq->iocb; 3655 3656 /* Find target node object */ 3657 ndlp = (NODELIST *)iocbq->node; 3658 3659 /* Get the iotag by registering the packet */ 3660 iotag = emlxs_register_pkt(cp, sbp); 3661 3662 if (!iotag) { 3663 /* 3664 * No more command slots available, retry later 3665 */ 3666 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3667 "Adapter Busy. Unable to allocate iotag: did=0x%x", did); 3668 3669 return (FC_TRAN_BUSY); 3670 } 3671 3672 /* Initalize iocbq */ 3673 iocbq->port = (void *) port; 3674 iocbq->channel = (void *) cp; 3675 3676 /* Indicate this is a FCP cmd */ 3677 iocbq->flag |= IOCB_FCP_CMD; 3678 3679 if (emlxs_bde_setup(port, sbp)) { 3680 /* Unregister the packet */ 3681 (void) emlxs_unregister_pkt(cp, iotag, 0); 3682 3683 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3684 "Adapter Busy. Unable to setup buffer list. did=%x", did); 3685 3686 return (FC_TRAN_BUSY); 3687 } 3688 /* Point of no return */ 3689 3690 /* Initalize iocb */ 3691 iocb->ULPCONTEXT = ndlp->nlp_Rpi; 3692 iocb->ULPIOTAG = iotag; 3693 iocb->ULPRSVDBYTE = 3694 ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 3695 iocb->ULPOWNER = OWN_CHIP; 3696 3697 switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 3698 case FC_TRAN_CLASS1: 3699 iocb->ULPCLASS = CLASS1; 3700 break; 3701 case FC_TRAN_CLASS2: 3702 iocb->ULPCLASS = CLASS2; 3703 /* iocb->ULPCLASS = CLASS3; */ 3704 break; 3705 case FC_TRAN_CLASS3: 3706 default: 3707 iocb->ULPCLASS = CLASS3; 3708 break; 3709 } 3710 3711 /* if device is FCP-2 device, set the following bit */ 3712 /* that says to run the FC-TAPE protocol. */ 3713 if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { 3714 iocb->ULPFCP2RCVY = 1; 3715 } 3716 3717 if (pkt->pkt_datalen == 0) { 3718 iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR; 3719 } else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) { 3720 iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR; 3721 iocb->ULPPU = PARM_READ_CHECK; 3722 iocb->un.fcpi64.fcpi_parm = pkt->pkt_datalen; 3723 } else { 3724 iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR; 3725 } 3726 3727 return (FC_SUCCESS); 3728 3729 } /* emlxs_sli3_prep_fcp_iocb() */ 3730 3731 3732 static uint32_t 3733 emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 3734 { 3735 emlxs_hba_t *hba = HBA; 3736 fc_packet_t *pkt; 3737 IOCBQ *iocbq; 3738 IOCB *iocb; 3739 CHANNEL *cp; 3740 NODELIST *ndlp; 3741 uint16_t iotag; 3742 uint32_t did; 3743 3744 pkt = PRIV2PKT(sbp); 3745 cp = &hba->chan[FC_IP_RING]; 3746 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 3747 3748 iocbq = &sbp->iocbq; 3749 iocb = &iocbq->iocb; 3750 ndlp = (NODELIST *)iocbq->node; 3751 3752 /* Get the iotag by registering the packet */ 3753 iotag = emlxs_register_pkt(cp, sbp); 3754 3755 if (!iotag) { 3756 /* 3757 * No more command slots available, retry later 3758 */ 3759 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3760 "Adapter Busy. Unable to allocate iotag: did=0x%x", did); 3761 3762 return (FC_TRAN_BUSY); 3763 } 3764 3765 /* Initalize iocbq */ 3766 iocbq->port = (void *) port; 3767 iocbq->channel = (void *) cp; 3768 3769 if (emlxs_bde_setup(port, sbp)) { 3770 /* Unregister the packet */ 3771 (void) emlxs_unregister_pkt(cp, iotag, 0); 3772 3773 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3774 "Adapter Busy. Unable to setup buffer list. did=%x", did); 3775 3776 return (FC_TRAN_BUSY); 3777 } 3778 /* Point of no return */ 3779 3780 /* Initalize iocb */ 3781 iocb->un.xseq64.w5.hcsw.Fctl = 0; 3782 3783 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_FIRST_SEQ) { 3784 iocb->un.xseq64.w5.hcsw.Fctl |= FSEQ; 3785 } 3786 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) { 3787 iocb->un.xseq64.w5.hcsw.Fctl |= SI; 3788 } 3789 3790 /* network headers */ 3791 iocb->un.xseq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl; 3792 iocb->un.xseq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl; 3793 iocb->un.xseq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type; 3794 3795 iocb->ULPIOTAG = iotag; 3796 iocb->ULPRSVDBYTE = 3797 ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 3798 iocb->ULPOWNER = OWN_CHIP; 3799 3800 if (pkt->pkt_tran_type == FC_PKT_BROADCAST) { 3801 HBASTATS.IpBcastIssued++; 3802 3803 iocb->ULPCOMMAND = CMD_XMIT_BCAST64_CN; 3804 iocb->ULPCONTEXT = 0; 3805 3806 if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { 3807 if (hba->topology != TOPOLOGY_LOOP) { 3808 iocb->ULPCT = 0x1; 3809 } 3810 iocb->ULPCONTEXT = port->vpi; 3811 } 3812 } else { 3813 HBASTATS.IpSeqIssued++; 3814 3815 iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX; 3816 iocb->ULPCONTEXT = ndlp->nlp_Xri; 3817 } 3818 3819 switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 3820 case FC_TRAN_CLASS1: 3821 iocb->ULPCLASS = CLASS1; 3822 break; 3823 case FC_TRAN_CLASS2: 3824 iocb->ULPCLASS = CLASS2; 3825 break; 3826 case FC_TRAN_CLASS3: 3827 default: 3828 iocb->ULPCLASS = CLASS3; 3829 break; 3830 } 3831 3832 return (FC_SUCCESS); 3833 3834 } /* emlxs_sli3_prep_ip_iocb() */ 3835 3836 3837 static uint32_t 3838 emlxs_sli3_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 3839 { 3840 emlxs_hba_t *hba = HBA; 3841 fc_packet_t *pkt; 3842 IOCBQ *iocbq; 3843 IOCB *iocb; 3844 CHANNEL *cp; 3845 uint16_t iotag; 3846 uint32_t did; 3847 uint32_t cmd; 3848 3849 pkt = PRIV2PKT(sbp); 3850 cp = &hba->chan[FC_ELS_RING]; 3851 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 3852 3853 iocbq = &sbp->iocbq; 3854 iocb = &iocbq->iocb; 3855 3856 3857 /* Get the iotag by registering the packet */ 3858 iotag = emlxs_register_pkt(cp, sbp); 3859 3860 if (!iotag) { 3861 /* 3862 * No more command slots available, retry later 3863 */ 3864 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3865 "Adapter Busy. Unable to allocate iotag. did=0x%x", did); 3866 3867 return (FC_TRAN_BUSY); 3868 } 3869 /* Initalize iocbq */ 3870 iocbq->port = (void *) port; 3871 iocbq->channel = (void *) cp; 3872 3873 if (emlxs_bde_setup(port, sbp)) { 3874 /* Unregister the packet */ 3875 (void) emlxs_unregister_pkt(cp, iotag, 0); 3876 3877 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3878 "Adapter Busy. Unable to setup buffer list. did=%x", did); 3879 3880 return (FC_TRAN_BUSY); 3881 } 3882 /* Point of no return */ 3883 3884 /* Initalize iocb */ 3885 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 3886 /* ELS Response */ 3887 iocb->ULPCONTEXT = (volatile uint16_t) pkt->pkt_cmd_fhdr.rx_id; 3888 iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX; 3889 } else { 3890 /* ELS Request */ 3891 iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did; 3892 iocb->ULPCONTEXT = 3893 (did == BCAST_DID) ? pkt->pkt_cmd_fhdr.seq_id : 0; 3894 iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR; 3895 3896 if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { 3897 if (hba->topology != TOPOLOGY_LOOP) { 3898 cmd = *((uint32_t *)pkt->pkt_cmd); 3899 cmd &= ELS_CMD_MASK; 3900 3901 if ((cmd == ELS_CMD_FLOGI) || 3902 (cmd == ELS_CMD_FDISC)) { 3903 iocb->ULPCT = 0x2; 3904 } else { 3905 iocb->ULPCT = 0x1; 3906 } 3907 } 3908 iocb->ULPCONTEXT = port->vpi; 3909 } 3910 } 3911 iocb->ULPIOTAG = iotag; 3912 iocb->ULPRSVDBYTE = 3913 ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 3914 iocb->ULPOWNER = OWN_CHIP; 3915 3916 switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 3917 case FC_TRAN_CLASS1: 3918 iocb->ULPCLASS = CLASS1; 3919 break; 3920 case FC_TRAN_CLASS2: 3921 iocb->ULPCLASS = CLASS2; 3922 break; 3923 case FC_TRAN_CLASS3: 3924 default: 3925 iocb->ULPCLASS = CLASS3; 3926 break; 3927 } 3928 sbp->class = iocb->ULPCLASS; 3929 3930 return (FC_SUCCESS); 3931 3932 } /* emlxs_sli3_prep_els_iocb() */ 3933 3934 3935 static uint32_t 3936 emlxs_sli3_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 3937 { 3938 emlxs_hba_t *hba = HBA; 3939 fc_packet_t *pkt; 3940 IOCBQ *iocbq; 3941 IOCB *iocb; 3942 CHANNEL *cp; 3943 NODELIST *ndlp; 3944 uint16_t iotag; 3945 uint32_t did; 3946 3947 pkt = PRIV2PKT(sbp); 3948 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 3949 cp = &hba->chan[FC_CT_RING]; 3950 3951 iocbq = &sbp->iocbq; 3952 iocb = &iocbq->iocb; 3953 ndlp = (NODELIST *)iocbq->node; 3954 3955 /* Get the iotag by registering the packet */ 3956 iotag = emlxs_register_pkt(cp, sbp); 3957 3958 if (!iotag) { 3959 /* 3960 * No more command slots available, retry later 3961 */ 3962 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3963 "Adapter Busy. Unable to allocate iotag. did=0x%x", did); 3964 3965 return (FC_TRAN_BUSY); 3966 } 3967 3968 if (emlxs_bde_setup(port, sbp)) { 3969 /* Unregister the packet */ 3970 (void) emlxs_unregister_pkt(cp, iotag, 0); 3971 3972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3973 "Adapter Busy. Unable to setup buffer list. did=%x", did); 3974 3975 return (FC_TRAN_BUSY); 3976 } 3977 3978 /* Point of no return */ 3979 3980 /* Initalize iocbq */ 3981 iocbq->port = (void *) port; 3982 iocbq->channel = (void *) cp; 3983 3984 /* Fill in rest of iocb */ 3985 iocb->un.genreq64.w5.hcsw.Fctl = LA; 3986 3987 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) { 3988 iocb->un.genreq64.w5.hcsw.Fctl |= LSEQ; 3989 } 3990 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) { 3991 iocb->un.genreq64.w5.hcsw.Fctl |= SI; 3992 } 3993 3994 /* Initalize iocb */ 3995 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 3996 /* CT Response */ 3997 iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX; 3998 iocb->un.genreq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl; 3999 iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id; 4000 } else { 4001 /* CT Request */ 4002 iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CR; 4003 iocb->un.genreq64.w5.hcsw.Dfctl = 0; 4004 iocb->ULPCONTEXT = ndlp->nlp_Rpi; 4005 } 4006 4007 iocb->un.genreq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl; 4008 iocb->un.genreq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type; 4009 4010 iocb->ULPIOTAG = iotag; 4011 iocb->ULPRSVDBYTE = 4012 ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 4013 iocb->ULPOWNER = OWN_CHIP; 4014 4015 switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 4016 case FC_TRAN_CLASS1: 4017 iocb->ULPCLASS = CLASS1; 4018 break; 4019 case FC_TRAN_CLASS2: 4020 iocb->ULPCLASS = CLASS2; 4021 break; 4022 case FC_TRAN_CLASS3: 4023 default: 4024 iocb->ULPCLASS = CLASS3; 4025 break; 4026 } 4027 4028 return (FC_SUCCESS); 4029 4030 } /* emlxs_sli3_prep_ct_iocb() */ 4031 4032 4033 #ifdef SFCT_SUPPORT 4034 static uint32_t 4035 emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 4036 { 4037 emlxs_hba_t *hba = HBA; 4038 uint32_t sgllen = 1; 4039 uint32_t rval; 4040 uint32_t size; 4041 uint32_t count; 4042 uint32_t resid; 4043 struct stmf_sglist_ent *sgl; 4044 4045 size = sbp->fct_buf->db_data_size; 4046 count = sbp->fct_buf->db_sglist_length; 4047 sgl = sbp->fct_buf->db_sglist; 4048 resid = size; 4049 4050 for (sgllen = 0; sgllen < count && resid > 0; sgllen++) { 4051 resid -= MIN(resid, sgl->seg_length); 4052 sgl++; 4053 } 4054 4055 if (resid > 0) { 4056 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4057 "emlxs_fct_bde_setup: Not enough scatter gather buffers " 4058 " size=%d resid=%d count=%d", 4059 size, resid, count); 4060 return (1); 4061 } 4062 4063 if ((hba->sli_mode < EMLXS_HBA_SLI3_MODE) || 4064 (sgllen > SLI3_MAX_BDE)) { 4065 rval = emlxs_sli2_fct_bde_setup(port, sbp); 4066 } else { 4067 rval = emlxs_sli3_fct_bde_setup(port, sbp); 4068 } 4069 4070 return (rval); 4071 4072 } /* emlxs_fct_bde_setup() */ 4073 #endif /* SFCT_SUPPORT */ 4074 4075 static uint32_t 4076 emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 4077 { 4078 uint32_t rval; 4079 emlxs_hba_t *hba = HBA; 4080 4081 if (hba->sli_mode < EMLXS_HBA_SLI3_MODE) { 4082 rval = emlxs_sli2_bde_setup(port, sbp); 4083 } else { 4084 rval = emlxs_sli3_bde_setup(port, sbp); 4085 } 4086 4087 return (rval); 4088 4089 } /* emlxs_bde_setup() */ 4090 4091 4092 static void 4093 emlxs_sli3_poll_intr(emlxs_hba_t *hba, uint32_t att_bit) 4094 { 4095 uint32_t ha_copy; 4096 4097 /* 4098 * Polling a specific attention bit. 4099 */ 4100 for (;;) { 4101 ha_copy = emlxs_check_attention(hba); 4102 4103 if (ha_copy & att_bit) { 4104 break; 4105 } 4106 4107 } 4108 4109 mutex_enter(&EMLXS_PORT_LOCK); 4110 ha_copy = emlxs_get_attention(hba, -1); 4111 mutex_exit(&EMLXS_PORT_LOCK); 4112 4113 /* Process the attentions */ 4114 emlxs_proc_attention(hba, ha_copy); 4115 4116 return; 4117 4118 } /* emlxs_sli3_poll_intr() */ 4119 4120 #ifdef MSI_SUPPORT 4121 static uint32_t 4122 emlxs_sli3_msi_intr(char *arg1, char *arg2) 4123 { 4124 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 4125 #ifdef FMA_SUPPORT 4126 emlxs_port_t *port = &PPORT; 4127 #endif /* FMA_SUPPORT */ 4128 uint16_t msgid; 4129 uint32_t hc_copy; 4130 uint32_t ha_copy; 4131 uint32_t restore = 0; 4132 4133 /* 4134 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 4135 * "emlxs_sli3_msi_intr: arg1=%p arg2=%p", arg1, arg2); 4136 */ 4137 4138 /* Check for legacy interrupt handling */ 4139 if (hba->intr_type == DDI_INTR_TYPE_FIXED) { 4140 mutex_enter(&EMLXS_PORT_LOCK); 4141 4142 if (hba->flag & FC_OFFLINE_MODE) { 4143 mutex_exit(&EMLXS_PORT_LOCK); 4144 4145 if (hba->bus_type == SBUS_FC) { 4146 return (DDI_INTR_CLAIMED); 4147 } else { 4148 return (DDI_INTR_UNCLAIMED); 4149 } 4150 } 4151 4152 /* Get host attention bits */ 4153 ha_copy = emlxs_get_attention(hba, -1); 4154 4155 if (ha_copy == 0) { 4156 if (hba->intr_unclaimed) { 4157 mutex_exit(&EMLXS_PORT_LOCK); 4158 return (DDI_INTR_UNCLAIMED); 4159 } 4160 4161 hba->intr_unclaimed = 1; 4162 } else { 4163 hba->intr_unclaimed = 0; 4164 } 4165 4166 mutex_exit(&EMLXS_PORT_LOCK); 4167 4168 /* Process the interrupt */ 4169 emlxs_proc_attention(hba, ha_copy); 4170 4171 return (DDI_INTR_CLAIMED); 4172 } 4173 4174 /* DDI_INTR_TYPE_MSI */ 4175 /* DDI_INTR_TYPE_MSIX */ 4176 4177 /* Get MSI message id */ 4178 msgid = (uint16_t)((unsigned long)arg2); 4179 4180 /* Validate the message id */ 4181 if (msgid >= hba->intr_count) { 4182 msgid = 0; 4183 } 4184 4185 mutex_enter(&EMLXS_INTR_LOCK(msgid)); 4186 4187 mutex_enter(&EMLXS_PORT_LOCK); 4188 4189 /* Check if adapter is offline */ 4190 if (hba->flag & FC_OFFLINE_MODE) { 4191 mutex_exit(&EMLXS_PORT_LOCK); 4192 mutex_exit(&EMLXS_INTR_LOCK(msgid)); 4193 4194 /* Always claim an MSI interrupt */ 4195 return (DDI_INTR_CLAIMED); 4196 } 4197 4198 /* Disable interrupts associated with this msgid */ 4199 if (msgid == 0 && (hba->model_info.chip == EMLXS_ZEPHYR_CHIP)) { 4200 hc_copy = hba->sli.sli3.hc_copy & ~hba->intr_mask; 4201 WRITE_CSR_REG(hba, FC_HC_REG(hba), hc_copy); 4202 restore = 1; 4203 } 4204 4205 /* Get host attention bits */ 4206 ha_copy = emlxs_get_attention(hba, msgid); 4207 4208 mutex_exit(&EMLXS_PORT_LOCK); 4209 4210 /* Process the interrupt */ 4211 emlxs_proc_attention(hba, ha_copy); 4212 4213 /* Restore interrupts */ 4214 if (restore) { 4215 mutex_enter(&EMLXS_PORT_LOCK); 4216 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 4217 #ifdef FMA_SUPPORT 4218 /* Access handle validation */ 4219 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 4220 #endif /* FMA_SUPPORT */ 4221 mutex_exit(&EMLXS_PORT_LOCK); 4222 } 4223 4224 mutex_exit(&EMLXS_INTR_LOCK(msgid)); 4225 4226 return (DDI_INTR_CLAIMED); 4227 4228 } /* emlxs_sli3_msi_intr() */ 4229 #endif /* MSI_SUPPORT */ 4230 4231 4232 static int 4233 emlxs_sli3_intx_intr(char *arg) 4234 { 4235 emlxs_hba_t *hba = (emlxs_hba_t *)arg; 4236 uint32_t ha_copy = 0; 4237 4238 mutex_enter(&EMLXS_PORT_LOCK); 4239 4240 if (hba->flag & FC_OFFLINE_MODE) { 4241 mutex_exit(&EMLXS_PORT_LOCK); 4242 4243 if (hba->bus_type == SBUS_FC) { 4244 return (DDI_INTR_CLAIMED); 4245 } else { 4246 return (DDI_INTR_UNCLAIMED); 4247 } 4248 } 4249 4250 /* Get host attention bits */ 4251 ha_copy = emlxs_get_attention(hba, -1); 4252 4253 if (ha_copy == 0) { 4254 if (hba->intr_unclaimed) { 4255 mutex_exit(&EMLXS_PORT_LOCK); 4256 return (DDI_INTR_UNCLAIMED); 4257 } 4258 4259 hba->intr_unclaimed = 1; 4260 } else { 4261 hba->intr_unclaimed = 0; 4262 } 4263 4264 mutex_exit(&EMLXS_PORT_LOCK); 4265 4266 /* Process the interrupt */ 4267 emlxs_proc_attention(hba, ha_copy); 4268 4269 return (DDI_INTR_CLAIMED); 4270 4271 } /* emlxs_sli3_intx_intr() */ 4272 4273 4274 /* EMLXS_PORT_LOCK must be held when call this routine */ 4275 static uint32_t 4276 emlxs_get_attention(emlxs_hba_t *hba, int32_t msgid) 4277 { 4278 #ifdef FMA_SUPPORT 4279 emlxs_port_t *port = &PPORT; 4280 #endif /* FMA_SUPPORT */ 4281 uint32_t ha_copy = 0; 4282 uint32_t ha_copy2; 4283 uint32_t mask = hba->sli.sli3.hc_copy; 4284 4285 #ifdef MSI_SUPPORT 4286 4287 read_ha_register: 4288 4289 /* Check for default MSI interrupt */ 4290 if (msgid == 0) { 4291 /* Read host attention register to determine interrupt source */ 4292 ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba)); 4293 4294 /* Filter out MSI non-default attention bits */ 4295 ha_copy2 &= ~(hba->intr_cond); 4296 } 4297 4298 /* Check for polled or fixed type interrupt */ 4299 else if (msgid == -1) { 4300 /* Read host attention register to determine interrupt source */ 4301 ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba)); 4302 } 4303 4304 /* Otherwise, assume a mapped MSI interrupt */ 4305 else { 4306 /* Convert MSI msgid to mapped attention bits */ 4307 ha_copy2 = hba->intr_map[msgid]; 4308 } 4309 4310 #else /* !MSI_SUPPORT */ 4311 4312 /* Read host attention register to determine interrupt source */ 4313 ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba)); 4314 4315 #endif /* MSI_SUPPORT */ 4316 4317 /* Check if Hardware error interrupt is enabled */ 4318 if ((ha_copy2 & HA_ERATT) && !(mask & HC_ERINT_ENA)) { 4319 ha_copy2 &= ~HA_ERATT; 4320 } 4321 4322 /* Check if link interrupt is enabled */ 4323 if ((ha_copy2 & HA_LATT) && !(mask & HC_LAINT_ENA)) { 4324 ha_copy2 &= ~HA_LATT; 4325 } 4326 4327 /* Check if Mailbox interrupt is enabled */ 4328 if ((ha_copy2 & HA_MBATT) && !(mask & HC_MBINT_ENA)) { 4329 ha_copy2 &= ~HA_MBATT; 4330 } 4331 4332 /* Check if ring0 interrupt is enabled */ 4333 if ((ha_copy2 & HA_R0ATT) && !(mask & HC_R0INT_ENA)) { 4334 ha_copy2 &= ~HA_R0ATT; 4335 } 4336 4337 /* Check if ring1 interrupt is enabled */ 4338 if ((ha_copy2 & HA_R1ATT) && !(mask & HC_R1INT_ENA)) { 4339 ha_copy2 &= ~HA_R1ATT; 4340 } 4341 4342 /* Check if ring2 interrupt is enabled */ 4343 if ((ha_copy2 & HA_R2ATT) && !(mask & HC_R2INT_ENA)) { 4344 ha_copy2 &= ~HA_R2ATT; 4345 } 4346 4347 /* Check if ring3 interrupt is enabled */ 4348 if ((ha_copy2 & HA_R3ATT) && !(mask & HC_R3INT_ENA)) { 4349 ha_copy2 &= ~HA_R3ATT; 4350 } 4351 4352 /* Accumulate attention bits */ 4353 ha_copy |= ha_copy2; 4354 4355 /* Clear attentions except for error, link, and autoclear(MSIX) */ 4356 ha_copy2 &= ~(HA_ERATT | HA_LATT); /* | hba->intr_autoClear */ 4357 4358 if (ha_copy2) { 4359 WRITE_CSR_REG(hba, FC_HA_REG(hba), ha_copy2); 4360 } 4361 4362 #ifdef FMA_SUPPORT 4363 /* Access handle validation */ 4364 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 4365 #endif /* FMA_SUPPORT */ 4366 4367 return (ha_copy); 4368 4369 } /* emlxs_get_attention() */ 4370 4371 4372 static void 4373 emlxs_proc_attention(emlxs_hba_t *hba, uint32_t ha_copy) 4374 { 4375 #ifdef FMA_SUPPORT 4376 emlxs_port_t *port = &PPORT; 4377 #endif /* FMA_SUPPORT */ 4378 4379 /* ha_copy should be pre-filtered */ 4380 4381 /* 4382 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4383 * "emlxs_proc_attention: ha_copy=%x", ha_copy); 4384 */ 4385 4386 if (hba->state < FC_WARM_START) { 4387 return; 4388 } 4389 4390 if (!ha_copy) { 4391 return; 4392 } 4393 4394 if (hba->bus_type == SBUS_FC) { 4395 (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba)); 4396 } 4397 4398 /* Adapter error */ 4399 if (ha_copy & HA_ERATT) { 4400 HBASTATS.IntrEvent[6]++; 4401 emlxs_handle_ff_error(hba); 4402 return; 4403 } 4404 4405 /* Mailbox interrupt */ 4406 if (ha_copy & HA_MBATT) { 4407 HBASTATS.IntrEvent[5]++; 4408 (void) emlxs_handle_mb_event(hba); 4409 } 4410 4411 /* Link Attention interrupt */ 4412 if (ha_copy & HA_LATT) { 4413 HBASTATS.IntrEvent[4]++; 4414 emlxs_sli3_handle_link_event(hba); 4415 } 4416 4417 /* event on ring 0 - FCP Ring */ 4418 if (ha_copy & HA_R0ATT) { 4419 HBASTATS.IntrEvent[0]++; 4420 emlxs_sli3_handle_ring_event(hba, 0, ha_copy); 4421 } 4422 4423 /* event on ring 1 - IP Ring */ 4424 if (ha_copy & HA_R1ATT) { 4425 HBASTATS.IntrEvent[1]++; 4426 emlxs_sli3_handle_ring_event(hba, 1, ha_copy); 4427 } 4428 4429 /* event on ring 2 - ELS Ring */ 4430 if (ha_copy & HA_R2ATT) { 4431 HBASTATS.IntrEvent[2]++; 4432 emlxs_sli3_handle_ring_event(hba, 2, ha_copy); 4433 } 4434 4435 /* event on ring 3 - CT Ring */ 4436 if (ha_copy & HA_R3ATT) { 4437 HBASTATS.IntrEvent[3]++; 4438 emlxs_sli3_handle_ring_event(hba, 3, ha_copy); 4439 } 4440 4441 if (hba->bus_type == SBUS_FC) { 4442 WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), SBUS_STAT_IP); 4443 } 4444 4445 /* Set heartbeat flag to show activity */ 4446 hba->heartbeat_flag = 1; 4447 4448 #ifdef FMA_SUPPORT 4449 if (hba->bus_type == SBUS_FC) { 4450 /* Access handle validation */ 4451 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle); 4452 } 4453 #endif /* FMA_SUPPORT */ 4454 4455 return; 4456 4457 } /* emlxs_proc_attention() */ 4458 4459 4460 /* 4461 * emlxs_handle_ff_error() 4462 * 4463 * Description: Processes a FireFly error 4464 * Runs at Interrupt level 4465 */ 4466 static void 4467 emlxs_handle_ff_error(emlxs_hba_t *hba) 4468 { 4469 emlxs_port_t *port = &PPORT; 4470 uint32_t status; 4471 uint32_t status1; 4472 uint32_t status2; 4473 int i = 0; 4474 4475 /* do what needs to be done, get error from STATUS REGISTER */ 4476 status = READ_CSR_REG(hba, FC_HS_REG(hba)); 4477 4478 /* Clear Chip error bit */ 4479 WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_ERATT); 4480 4481 /* If HS_FFER1 is set, then wait until the HS_FFER1 bit clears */ 4482 if (status & HS_FFER1) { 4483 4484 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4485 "HS_FFER1 received"); 4486 EMLXS_STATE_CHANGE(hba, FC_ERROR); 4487 (void) emlxs_offline(hba); 4488 while ((status & HS_FFER1) && (i < 300)) { 4489 status = 4490 READ_CSR_REG(hba, FC_HS_REG(hba)); 4491 DELAYMS(1000); 4492 i++; 4493 } 4494 } 4495 4496 if (i == 300) { 4497 /* 5 minutes is up, shutdown HBA */ 4498 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4499 "HS_FFER1 clear timeout"); 4500 4501 EMLXS_STATE_CHANGE(hba, FC_ERROR); 4502 emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); 4503 4504 goto done; 4505 } 4506 4507 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4508 "HS_FFER1 cleared"); 4509 4510 if (status & HS_OVERTEMP) { 4511 status1 = 4512 READ_SLIM_ADDR(hba, 4513 ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xb0)); 4514 4515 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4516 "Maximum adapter temperature exceeded (%d �C).", status1); 4517 4518 hba->temperature = status1; 4519 hba->flag |= FC_OVERTEMP_EVENT; 4520 4521 EMLXS_STATE_CHANGE(hba, FC_ERROR); 4522 emlxs_thread_spawn(hba, emlxs_shutdown_thread, 4523 NULL, NULL); 4524 4525 } else { 4526 status1 = 4527 READ_SLIM_ADDR(hba, 4528 ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xa8)); 4529 status2 = 4530 READ_SLIM_ADDR(hba, 4531 ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xac)); 4532 4533 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4534 "Host Error Attention: " 4535 "status=0x%x status1=0x%x status2=0x%x", 4536 status, status1, status2); 4537 4538 EMLXS_STATE_CHANGE(hba, FC_ERROR); 4539 4540 if (status & HS_FFER6) { 4541 emlxs_thread_spawn(hba, emlxs_restart_thread, 4542 NULL, NULL); 4543 } else { 4544 emlxs_thread_spawn(hba, emlxs_shutdown_thread, 4545 NULL, NULL); 4546 } 4547 } 4548 4549 done: 4550 #ifdef FMA_SUPPORT 4551 /* Access handle validation */ 4552 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 4553 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 4554 #endif /* FMA_SUPPORT */ 4555 4556 return; 4557 4558 } /* emlxs_handle_ff_error() */ 4559 4560 4561 /* 4562 * emlxs_sli3_handle_link_event() 4563 * 4564 * Description: Process a Link Attention. 4565 */ 4566 static void 4567 emlxs_sli3_handle_link_event(emlxs_hba_t *hba) 4568 { 4569 emlxs_port_t *port = &PPORT; 4570 MAILBOXQ *mbq; 4571 int rc; 4572 4573 HBASTATS.LinkEvent++; 4574 4575 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_event_msg, "event=%x", 4576 HBASTATS.LinkEvent); 4577 4578 /* Make sure link is declared down */ 4579 emlxs_linkdown(hba); 4580 4581 4582 /* Get a buffer which will be used for mailbox commands */ 4583 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 4584 /* Get link attention message */ 4585 if (emlxs_mb_read_la(hba, mbq) == 0) { 4586 rc = emlxs_sli3_issue_mbox_cmd(hba, mbq, 4587 MBX_NOWAIT, 0); 4588 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 4589 emlxs_mem_put(hba, MEM_MBOX, 4590 (void *)mbq); 4591 } 4592 4593 mutex_enter(&EMLXS_PORT_LOCK); 4594 4595 4596 /* 4597 * Clear Link Attention in HA REG 4598 */ 4599 WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_LATT); 4600 4601 #ifdef FMA_SUPPORT 4602 /* Access handle validation */ 4603 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 4604 #endif /* FMA_SUPPORT */ 4605 4606 mutex_exit(&EMLXS_PORT_LOCK); 4607 } else { 4608 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 4609 } 4610 } 4611 4612 } /* emlxs_sli3_handle_link_event() */ 4613 4614 4615 /* 4616 * emlxs_sli3_handle_ring_event() 4617 * 4618 * Description: Process a Ring Attention. 4619 */ 4620 static void 4621 emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no, 4622 uint32_t ha_copy) 4623 { 4624 emlxs_port_t *port = &PPORT; 4625 SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; 4626 CHANNEL *cp; 4627 RING *rp; 4628 IOCB *entry; 4629 IOCBQ *iocbq; 4630 IOCBQ local_iocbq; 4631 PGP *pgp; 4632 uint32_t count; 4633 volatile uint32_t chipatt; 4634 void *ioa2; 4635 uint32_t reg; 4636 uint32_t channel_no; 4637 off_t offset; 4638 IOCBQ *rsp_head = NULL; 4639 IOCBQ *rsp_tail = NULL; 4640 emlxs_buf_t *sbp = NULL; 4641 4642 count = 0; 4643 rp = &hba->sli.sli3.ring[ring_no]; 4644 cp = rp->channelp; 4645 channel_no = cp->channelno; 4646 4647 /* 4648 * Isolate this ring's host attention bits 4649 * This makes all ring attention bits equal 4650 * to Ring0 attention bits 4651 */ 4652 reg = (ha_copy >> (ring_no * 4)) & 0x0f; 4653 4654 /* 4655 * Gather iocb entries off response ring. 4656 * Ensure entry is owned by the host. 4657 */ 4658 pgp = (PGP *)&slim2p->mbx.us.s2.port[ring_no]; 4659 offset = 4660 (off_t)((uint64_t)((unsigned long)&(pgp->rspPutInx)) - 4661 (uint64_t)((unsigned long)slim2p)); 4662 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 4663 DDI_DMA_SYNC_FORKERNEL); 4664 rp->fc_port_rspidx = BE_SWAP32(pgp->rspPutInx); 4665 4666 /* While ring is not empty */ 4667 while (rp->fc_rspidx != rp->fc_port_rspidx) { 4668 HBASTATS.IocbReceived[channel_no]++; 4669 4670 /* Get the next response ring iocb */ 4671 entry = 4672 (IOCB *)(((char *)rp->fc_rspringaddr + 4673 (rp->fc_rspidx * hba->sli.sli3.iocb_rsp_size))); 4674 4675 /* DMA sync the response ring iocb for the adapter */ 4676 offset = (off_t)((uint64_t)((unsigned long)entry) 4677 - (uint64_t)((unsigned long)slim2p)); 4678 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4679 hba->sli.sli3.iocb_rsp_size, DDI_DMA_SYNC_FORKERNEL); 4680 4681 count++; 4682 4683 /* Copy word6 and word7 to local iocb for now */ 4684 iocbq = &local_iocbq; 4685 4686 BE_SWAP32_BCOPY((uint8_t *)entry + (sizeof (uint32_t) * 6), 4687 (uint8_t *)iocbq + (sizeof (uint32_t) * 6), 4688 (sizeof (uint32_t) * 2)); 4689 4690 /* when LE is not set, entire Command has not been received */ 4691 if (!iocbq->iocb.ULPLE) { 4692 /* This should never happen */ 4693 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_error_msg, 4694 "ulpLE is not set. " 4695 "ring=%d iotag=%x cmd=%x status=%x", 4696 channel_no, iocbq->iocb.ULPIOTAG, 4697 iocbq->iocb.ULPCOMMAND, iocbq->iocb.ULPSTATUS); 4698 4699 goto next; 4700 } 4701 4702 switch (iocbq->iocb.ULPCOMMAND) { 4703 #ifdef SFCT_SUPPORT 4704 case CMD_CLOSE_XRI_CX: 4705 case CMD_CLOSE_XRI_CN: 4706 case CMD_ABORT_XRI_CX: 4707 if (!port->tgt_mode) { 4708 sbp = NULL; 4709 break; 4710 } 4711 4712 sbp = 4713 emlxs_unregister_pkt(cp, iocbq->iocb.ULPIOTAG, 0); 4714 break; 4715 #endif /* SFCT_SUPPORT */ 4716 4717 /* Ring 0 registered commands */ 4718 case CMD_FCP_ICMND_CR: 4719 case CMD_FCP_ICMND_CX: 4720 case CMD_FCP_IREAD_CR: 4721 case CMD_FCP_IREAD_CX: 4722 case CMD_FCP_IWRITE_CR: 4723 case CMD_FCP_IWRITE_CX: 4724 case CMD_FCP_ICMND64_CR: 4725 case CMD_FCP_ICMND64_CX: 4726 case CMD_FCP_IREAD64_CR: 4727 case CMD_FCP_IREAD64_CX: 4728 case CMD_FCP_IWRITE64_CR: 4729 case CMD_FCP_IWRITE64_CX: 4730 #ifdef SFCT_SUPPORT 4731 case CMD_FCP_TSEND_CX: 4732 case CMD_FCP_TSEND64_CX: 4733 case CMD_FCP_TRECEIVE_CX: 4734 case CMD_FCP_TRECEIVE64_CX: 4735 case CMD_FCP_TRSP_CX: 4736 case CMD_FCP_TRSP64_CX: 4737 #endif /* SFCT_SUPPORT */ 4738 4739 /* Ring 1 registered commands */ 4740 case CMD_XMIT_BCAST_CN: 4741 case CMD_XMIT_BCAST_CX: 4742 case CMD_XMIT_SEQUENCE_CX: 4743 case CMD_XMIT_SEQUENCE_CR: 4744 case CMD_XMIT_BCAST64_CN: 4745 case CMD_XMIT_BCAST64_CX: 4746 case CMD_XMIT_SEQUENCE64_CX: 4747 case CMD_XMIT_SEQUENCE64_CR: 4748 case CMD_CREATE_XRI_CR: 4749 case CMD_CREATE_XRI_CX: 4750 4751 /* Ring 2 registered commands */ 4752 case CMD_ELS_REQUEST_CR: 4753 case CMD_ELS_REQUEST_CX: 4754 case CMD_XMIT_ELS_RSP_CX: 4755 case CMD_ELS_REQUEST64_CR: 4756 case CMD_ELS_REQUEST64_CX: 4757 case CMD_XMIT_ELS_RSP64_CX: 4758 4759 /* Ring 3 registered commands */ 4760 case CMD_GEN_REQUEST64_CR: 4761 case CMD_GEN_REQUEST64_CX: 4762 4763 sbp = 4764 emlxs_unregister_pkt(cp, iocbq->iocb.ULPIOTAG, 0); 4765 break; 4766 4767 default: 4768 sbp = NULL; 4769 } 4770 4771 /* If packet is stale, then drop it. */ 4772 if (sbp == STALE_PACKET) { 4773 cp->hbaCmplCmd_sbp++; 4774 /* Copy entry to the local iocbq */ 4775 BE_SWAP32_BCOPY((uint8_t *)entry, 4776 (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size); 4777 4778 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg, 4779 "channelno=%d iocb=%p cmd=%x status=%x " 4780 "error=%x iotag=%x context=%x info=%x", 4781 channel_no, iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND, 4782 iocbq->iocb.ULPSTATUS, 4783 (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError, 4784 (uint16_t)iocbq->iocb.ULPIOTAG, 4785 (uint16_t)iocbq->iocb.ULPCONTEXT, 4786 (uint8_t)iocbq->iocb.ULPRSVDBYTE); 4787 4788 goto next; 4789 } 4790 4791 /* 4792 * If a packet was found, then queue the packet's 4793 * iocb for deferred processing 4794 */ 4795 else if (sbp) { 4796 #ifdef SFCT_SUPPORT 4797 fct_cmd_t *fct_cmd; 4798 emlxs_buf_t *cmd_sbp; 4799 4800 fct_cmd = sbp->fct_cmd; 4801 if (fct_cmd) { 4802 cmd_sbp = 4803 (emlxs_buf_t *)fct_cmd->cmd_fca_private; 4804 mutex_enter(&cmd_sbp->fct_mtx); 4805 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 4806 EMLXS_FCT_IOCB_COMPLETE); 4807 mutex_exit(&cmd_sbp->fct_mtx); 4808 } 4809 #endif /* SFCT_SUPPORT */ 4810 cp->hbaCmplCmd_sbp++; 4811 atomic_add_32(&hba->io_active, -1); 4812 4813 /* Copy entry to sbp's iocbq */ 4814 iocbq = &sbp->iocbq; 4815 BE_SWAP32_BCOPY((uint8_t *)entry, 4816 (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size); 4817 4818 iocbq->next = NULL; 4819 4820 /* 4821 * If this is NOT a polled command completion 4822 * or a driver allocated pkt, then defer pkt 4823 * completion. 4824 */ 4825 if (!(sbp->pkt_flags & 4826 (PACKET_POLLED | PACKET_ALLOCATED))) { 4827 /* Add the IOCB to the local list */ 4828 if (!rsp_head) { 4829 rsp_head = iocbq; 4830 } else { 4831 rsp_tail->next = iocbq; 4832 } 4833 4834 rsp_tail = iocbq; 4835 4836 goto next; 4837 } 4838 } else { 4839 cp->hbaCmplCmd++; 4840 /* Copy entry to the local iocbq */ 4841 BE_SWAP32_BCOPY((uint8_t *)entry, 4842 (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size); 4843 4844 iocbq->next = NULL; 4845 iocbq->bp = NULL; 4846 iocbq->port = &PPORT; 4847 iocbq->channel = cp; 4848 iocbq->node = NULL; 4849 iocbq->sbp = NULL; 4850 iocbq->flag = 0; 4851 } 4852 4853 /* process the channel event now */ 4854 emlxs_proc_channel_event(hba, cp, iocbq); 4855 4856 next: 4857 /* Increment the driver's local response get index */ 4858 if (++rp->fc_rspidx >= rp->fc_numRiocb) { 4859 rp->fc_rspidx = 0; 4860 } 4861 4862 } /* while (TRUE) */ 4863 4864 if (rsp_head) { 4865 mutex_enter(&cp->rsp_lock); 4866 if (cp->rsp_head == NULL) { 4867 cp->rsp_head = rsp_head; 4868 cp->rsp_tail = rsp_tail; 4869 } else { 4870 cp->rsp_tail->next = rsp_head; 4871 cp->rsp_tail = rsp_tail; 4872 } 4873 mutex_exit(&cp->rsp_lock); 4874 4875 emlxs_thread_trigger2(&cp->intr_thread, emlxs_proc_channel, cp); 4876 } 4877 4878 /* Check if at least one response entry was processed */ 4879 if (count) { 4880 /* Update response get index for the adapter */ 4881 if (hba->bus_type == SBUS_FC) { 4882 slim2p->mbx.us.s2.host[channel_no].rspGetInx 4883 = BE_SWAP32(rp->fc_rspidx); 4884 4885 /* DMA sync the index for the adapter */ 4886 offset = (off_t) 4887 ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2. 4888 host[channel_no].rspGetInx)) 4889 - (uint64_t)((unsigned long)slim2p)); 4890 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 4891 offset, 4, DDI_DMA_SYNC_FORDEV); 4892 } else { 4893 ioa2 = 4894 (void *)((char *)hba->sli.sli3.slim_addr + 4895 hba->sli.sli3.hgp_ring_offset + (((channel_no * 2) + 4896 1) * sizeof (uint32_t))); 4897 WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, 4898 rp->fc_rspidx); 4899 #ifdef FMA_SUPPORT 4900 /* Access handle validation */ 4901 EMLXS_CHK_ACC_HANDLE(hba, 4902 hba->sli.sli3.slim_acc_handle); 4903 #endif /* FMA_SUPPORT */ 4904 } 4905 4906 if (reg & HA_R0RE_REQ) { 4907 /* HBASTATS.chipRingFree++; */ 4908 4909 mutex_enter(&EMLXS_PORT_LOCK); 4910 4911 /* Tell the adapter we serviced the ring */ 4912 chipatt = ((CA_R0ATT | CA_R0RE_RSP) << 4913 (channel_no * 4)); 4914 WRITE_CSR_REG(hba, FC_CA_REG(hba), chipatt); 4915 4916 #ifdef FMA_SUPPORT 4917 /* Access handle validation */ 4918 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 4919 #endif /* FMA_SUPPORT */ 4920 4921 mutex_exit(&EMLXS_PORT_LOCK); 4922 } 4923 } 4924 4925 if ((reg & HA_R0CE_RSP) || hba->channel_tx_count) { 4926 /* HBASTATS.hostRingFree++; */ 4927 4928 /* Cmd ring may be available. Try sending more iocbs */ 4929 emlxs_sli3_issue_iocb_cmd(hba, cp, 0); 4930 } 4931 4932 /* HBASTATS.ringEvent++; */ 4933 4934 return; 4935 4936 } /* emlxs_sli3_handle_ring_event() */ 4937 4938 4939 extern int 4940 emlxs_handle_rcv_seq(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 4941 { 4942 emlxs_port_t *port = &PPORT; 4943 IOCB *iocb; 4944 RING *rp; 4945 MATCHMAP *mp = NULL; 4946 uint64_t bdeAddr; 4947 uint32_t vpi = 0; 4948 uint32_t channelno; 4949 uint32_t size = 0; 4950 uint32_t *RcvError; 4951 uint32_t *RcvDropped; 4952 uint32_t *UbPosted; 4953 emlxs_msg_t *dropped_msg; 4954 char error_str[64]; 4955 uint32_t buf_type; 4956 uint32_t *word; 4957 uint32_t hbq_id; 4958 4959 channelno = cp->channelno; 4960 rp = &hba->sli.sli3.ring[channelno]; 4961 4962 iocb = &iocbq->iocb; 4963 word = (uint32_t *)iocb; 4964 4965 switch (channelno) { 4966 #ifdef SFCT_SUPPORT 4967 case FC_FCT_RING: 4968 HBASTATS.FctRingEvent++; 4969 RcvError = &HBASTATS.FctRingError; 4970 RcvDropped = &HBASTATS.FctRingDropped; 4971 UbPosted = &HBASTATS.FctUbPosted; 4972 dropped_msg = &emlxs_fct_detail_msg; 4973 buf_type = MEM_FCTBUF; 4974 break; 4975 #endif /* SFCT_SUPPORT */ 4976 4977 case FC_IP_RING: 4978 HBASTATS.IpRcvEvent++; 4979 RcvError = &HBASTATS.IpDropped; 4980 RcvDropped = &HBASTATS.IpDropped; 4981 UbPosted = &HBASTATS.IpUbPosted; 4982 dropped_msg = &emlxs_unsol_ip_dropped_msg; 4983 buf_type = MEM_IPBUF; 4984 break; 4985 4986 case FC_ELS_RING: 4987 HBASTATS.ElsRcvEvent++; 4988 RcvError = &HBASTATS.ElsRcvError; 4989 RcvDropped = &HBASTATS.ElsRcvDropped; 4990 UbPosted = &HBASTATS.ElsUbPosted; 4991 dropped_msg = &emlxs_unsol_els_dropped_msg; 4992 buf_type = MEM_ELSBUF; 4993 break; 4994 4995 case FC_CT_RING: 4996 HBASTATS.CtRcvEvent++; 4997 RcvError = &HBASTATS.CtRcvError; 4998 RcvDropped = &HBASTATS.CtRcvDropped; 4999 UbPosted = &HBASTATS.CtUbPosted; 5000 dropped_msg = &emlxs_unsol_ct_dropped_msg; 5001 buf_type = MEM_CTBUF; 5002 break; 5003 5004 default: 5005 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 5006 "channel=%d cmd=%x %s %x %x %x %x", 5007 channelno, iocb->ULPCOMMAND, 5008 emlxs_state_xlate(iocb->ULPSTATUS), word[4], word[5], 5009 word[6], word[7]); 5010 return (1); 5011 } 5012 5013 if (iocb->ULPSTATUS) { 5014 if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) && 5015 (iocb->un.grsp.perr.statLocalError == 5016 IOERR_RCV_BUFFER_TIMEOUT)) { 5017 (void) strcpy(error_str, "Out of posted buffers:"); 5018 } else if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) && 5019 (iocb->un.grsp.perr.statLocalError == 5020 IOERR_RCV_BUFFER_WAITING)) { 5021 (void) strcpy(error_str, "Buffer waiting:"); 5022 goto done; 5023 } else if (iocb->ULPSTATUS == IOSTAT_NEED_BUFF_ENTRY) { 5024 (void) strcpy(error_str, "Need Buffer Entry:"); 5025 goto done; 5026 } else { 5027 (void) strcpy(error_str, "General error:"); 5028 } 5029 5030 goto failed; 5031 } 5032 5033 if (hba->flag & FC_HBQ_ENABLED) { 5034 HBQ_INIT_t *hbq; 5035 HBQE_t *hbqE; 5036 uint32_t hbqe_tag; 5037 5038 (*UbPosted)--; 5039 5040 hbqE = (HBQE_t *)iocb; 5041 hbq_id = hbqE->unt.ext.HBQ_tag; 5042 hbqe_tag = hbqE->unt.ext.HBQE_tag; 5043 5044 hbq = &hba->sli.sli3.hbq_table[hbq_id]; 5045 5046 if (hbqe_tag >= hbq->HBQ_numEntries) { 5047 (void) sprintf(error_str, "Invalid HBQE tag=%x:", 5048 hbqe_tag); 5049 goto dropped; 5050 } 5051 5052 mp = hba->sli.sli3.hbq_table[hbq_id].HBQ_PostBufs[hbqe_tag]; 5053 5054 size = iocb->unsli3.ext_rcv.seq_len; 5055 } else { 5056 bdeAddr = 5057 PADDR(iocb->un.cont64[0].addrHigh, 5058 iocb->un.cont64[0].addrLow); 5059 5060 /* Check for invalid buffer */ 5061 if (iocb->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID) { 5062 (void) strcpy(error_str, "Invalid buffer:"); 5063 goto dropped; 5064 } 5065 5066 mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr); 5067 5068 size = iocb->un.rcvseq64.rcvBde.tus.f.bdeSize; 5069 } 5070 5071 if (!mp) { 5072 (void) strcpy(error_str, "Buffer not mapped:"); 5073 goto dropped; 5074 } 5075 5076 #ifdef FMA_SUPPORT 5077 if (mp->dma_handle) { 5078 if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) 5079 != DDI_FM_OK) { 5080 EMLXS_MSGF(EMLXS_CONTEXT, 5081 &emlxs_invalid_dma_handle_msg, 5082 "emlxs_handle_rcv_seq: hdl=%p", 5083 mp->dma_handle); 5084 goto dropped; 5085 } 5086 } 5087 #endif /* FMA_SUPPORT */ 5088 5089 if (!size) { 5090 (void) strcpy(error_str, "Buffer empty:"); 5091 goto dropped; 5092 } 5093 5094 /* To avoid we drop the broadcast packets */ 5095 if (channelno != FC_IP_RING) { 5096 /* Get virtual port */ 5097 if (hba->flag & FC_NPIV_ENABLED) { 5098 vpi = iocb->unsli3.ext_rcv.vpi; 5099 if (vpi >= hba->vpi_max) { 5100 (void) sprintf(error_str, 5101 "Invalid VPI=%d:", vpi); 5102 goto dropped; 5103 } 5104 5105 port = &VPORT(vpi); 5106 } 5107 } 5108 5109 /* Process request */ 5110 switch (channelno) { 5111 #ifdef SFCT_SUPPORT 5112 case FC_FCT_RING: 5113 (void) emlxs_fct_handle_unsol_req(port, cp, iocbq, mp, size); 5114 break; 5115 #endif /* SFCT_SUPPORT */ 5116 5117 case FC_IP_RING: 5118 (void) emlxs_ip_handle_unsol_req(port, cp, iocbq, mp, size); 5119 break; 5120 5121 case FC_ELS_RING: 5122 /* If this is a target port, then let fct handle this */ 5123 if (port->ini_mode) { 5124 (void) emlxs_els_handle_unsol_req(port, cp, iocbq, mp, 5125 size); 5126 } 5127 #ifdef SFCT_SUPPORT 5128 else if (port->tgt_mode) { 5129 (void) emlxs_fct_handle_unsol_els(port, cp, iocbq, mp, 5130 size); 5131 } 5132 #endif /* SFCT_SUPPORT */ 5133 break; 5134 5135 case FC_CT_RING: 5136 (void) emlxs_ct_handle_unsol_req(port, cp, iocbq, mp, size); 5137 break; 5138 } 5139 5140 goto done; 5141 5142 dropped: 5143 (*RcvDropped)++; 5144 5145 EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg, 5146 "%s: cmd=%x %s %x %x %x %x", 5147 error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS), 5148 word[4], word[5], word[6], word[7]); 5149 5150 if (channelno == FC_FCT_RING) { 5151 uint32_t sid; 5152 5153 if (hba->sli_mode >= EMLXS_HBA_SLI3_MODE) { 5154 emlxs_node_t *ndlp; 5155 ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG); 5156 sid = ndlp->nlp_DID; 5157 } else { 5158 sid = iocb->un.ulpWord[4] & 0xFFFFFF; 5159 } 5160 5161 emlxs_send_logo(port, sid); 5162 } 5163 5164 goto done; 5165 5166 failed: 5167 (*RcvError)++; 5168 5169 EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg, 5170 "%s: cmd=%x %s %x %x %x %x hba:%x %x", 5171 error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS), 5172 word[4], word[5], word[6], word[7], hba->state, hba->flag); 5173 5174 done: 5175 5176 if (hba->flag & FC_HBQ_ENABLED) { 5177 emlxs_update_HBQ_index(hba, hbq_id); 5178 } else { 5179 if (mp) { 5180 emlxs_mem_put(hba, buf_type, (void *)mp); 5181 } 5182 (void) emlxs_post_buffer(hba, rp, 1); 5183 } 5184 5185 return (0); 5186 5187 } /* emlxs_handle_rcv_seq() */ 5188 5189 5190 /* EMLXS_CMD_RING_LOCK must be held when calling this function */ 5191 static void 5192 emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 5193 { 5194 emlxs_port_t *port; 5195 IOCB *icmd; 5196 IOCB *iocb; 5197 emlxs_buf_t *sbp; 5198 off_t offset; 5199 uint32_t ringno; 5200 5201 ringno = rp->ringno; 5202 sbp = iocbq->sbp; 5203 icmd = &iocbq->iocb; 5204 port = iocbq->port; 5205 5206 HBASTATS.IocbIssued[ringno]++; 5207 5208 /* Check for ULP pkt request */ 5209 if (sbp) { 5210 mutex_enter(&sbp->mtx); 5211 5212 if (sbp->node == NULL) { 5213 /* Set node to base node by default */ 5214 iocbq->node = (void *)&port->node_base; 5215 sbp->node = (void *)&port->node_base; 5216 } 5217 5218 sbp->pkt_flags |= PACKET_IN_CHIPQ; 5219 mutex_exit(&sbp->mtx); 5220 5221 atomic_add_32(&hba->io_active, 1); 5222 5223 #ifdef SFCT_SUPPORT 5224 #ifdef FCT_IO_TRACE 5225 if (sbp->fct_cmd) { 5226 emlxs_fct_io_trace(port, sbp->fct_cmd, 5227 EMLXS_FCT_IOCB_ISSUED); 5228 emlxs_fct_io_trace(port, sbp->fct_cmd, 5229 icmd->ULPCOMMAND); 5230 } 5231 #endif /* FCT_IO_TRACE */ 5232 #endif /* SFCT_SUPPORT */ 5233 5234 rp->channelp->hbaSendCmd_sbp++; 5235 iocbq->channel = rp->channelp; 5236 } else { 5237 rp->channelp->hbaSendCmd++; 5238 } 5239 5240 /* get the next available command ring iocb */ 5241 iocb = 5242 (IOCB *)(((char *)rp->fc_cmdringaddr + 5243 (rp->fc_cmdidx * hba->sli.sli3.iocb_cmd_size))); 5244 5245 /* Copy the local iocb to the command ring iocb */ 5246 BE_SWAP32_BCOPY((uint8_t *)icmd, (uint8_t *)iocb, 5247 hba->sli.sli3.iocb_cmd_size); 5248 5249 /* DMA sync the command ring iocb for the adapter */ 5250 offset = (off_t)((uint64_t)((unsigned long)iocb) 5251 - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5252 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 5253 hba->sli.sli3.iocb_cmd_size, DDI_DMA_SYNC_FORDEV); 5254 5255 /* 5256 * After this, the sbp / iocb should not be 5257 * accessed in the xmit path. 5258 */ 5259 5260 /* Free the local iocb if there is no sbp tracking it */ 5261 if (!sbp) { 5262 emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 5263 } 5264 5265 /* update local ring index to next available ring index */ 5266 rp->fc_cmdidx = 5267 (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1; 5268 5269 5270 return; 5271 5272 } /* emlxs_sli3_issue_iocb() */ 5273 5274 5275 static void 5276 emlxs_sli3_hba_kill(emlxs_hba_t *hba) 5277 { 5278 emlxs_port_t *port = &PPORT; 5279 MAILBOX *swpmb; 5280 MAILBOX *mb2; 5281 MAILBOX *mb1; 5282 uint32_t word0; 5283 uint32_t j; 5284 uint32_t interlock_failed; 5285 uint32_t ha_copy; 5286 uint32_t value; 5287 off_t offset; 5288 uint32_t size; 5289 5290 /* Perform adapter interlock to kill adapter */ 5291 interlock_failed = 0; 5292 5293 mutex_enter(&EMLXS_PORT_LOCK); 5294 if (hba->flag & FC_INTERLOCKED) { 5295 EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 5296 5297 mutex_exit(&EMLXS_PORT_LOCK); 5298 5299 return; 5300 } 5301 5302 j = 0; 5303 while (j++ < 10000) { 5304 if (hba->mbox_queue_flag == 0) { 5305 break; 5306 } 5307 5308 mutex_exit(&EMLXS_PORT_LOCK); 5309 DELAYUS(100); 5310 mutex_enter(&EMLXS_PORT_LOCK); 5311 } 5312 5313 if (hba->mbox_queue_flag != 0) { 5314 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5315 "Interlock failed. Mailbox busy."); 5316 mutex_exit(&EMLXS_PORT_LOCK); 5317 return; 5318 } 5319 5320 hba->flag |= FC_INTERLOCKED; 5321 hba->mbox_queue_flag = 1; 5322 5323 /* Disable all host interrupts */ 5324 hba->sli.sli3.hc_copy = 0; 5325 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 5326 WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff); 5327 5328 mb2 = FC_SLIM2_MAILBOX(hba); 5329 mb1 = FC_SLIM1_MAILBOX(hba); 5330 swpmb = (MAILBOX *)&word0; 5331 5332 if (!(hba->flag & FC_SLIM2_MODE)) { 5333 goto mode_B; 5334 } 5335 5336 mode_A: 5337 5338 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5339 "Attempting SLIM2 Interlock..."); 5340 5341 interlock_A: 5342 5343 value = 0x55555555; 5344 word0 = 0; 5345 swpmb->mbxCommand = MBX_KILL_BOARD; 5346 swpmb->mbxOwner = OWN_CHIP; 5347 5348 /* Write value to SLIM */ 5349 WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value); 5350 WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0); 5351 5352 /* Send Kill board request */ 5353 mb2->un.varWords[0] = value; 5354 mb2->mbxCommand = MBX_KILL_BOARD; 5355 mb2->mbxOwner = OWN_CHIP; 5356 5357 /* Sync the memory */ 5358 offset = (off_t)((uint64_t)((unsigned long)mb2) 5359 - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5360 size = (sizeof (uint32_t) * 2); 5361 5362 BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size); 5363 5364 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size, 5365 DDI_DMA_SYNC_FORDEV); 5366 5367 /* interrupt board to do it right away */ 5368 WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 5369 5370 /* First wait for command acceptence */ 5371 j = 0; 5372 while (j++ < 1000) { 5373 value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); 5374 5375 if (value == 0xAAAAAAAA) { 5376 break; 5377 } 5378 5379 DELAYUS(50); 5380 } 5381 5382 if (value == 0xAAAAAAAA) { 5383 /* Now wait for mailbox ownership to clear */ 5384 while (j++ < 10000) { 5385 word0 = 5386 READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1)); 5387 5388 if (swpmb->mbxOwner == 0) { 5389 break; 5390 } 5391 5392 DELAYUS(50); 5393 } 5394 5395 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5396 "Interlock succeeded."); 5397 5398 goto done; 5399 } 5400 5401 /* Interlock failed !!! */ 5402 interlock_failed = 1; 5403 5404 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "Interlock failed."); 5405 5406 mode_B: 5407 5408 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5409 "Attempting SLIM1 Interlock..."); 5410 5411 interlock_B: 5412 5413 value = 0x55555555; 5414 word0 = 0; 5415 swpmb->mbxCommand = MBX_KILL_BOARD; 5416 swpmb->mbxOwner = OWN_CHIP; 5417 5418 /* Write KILL BOARD to mailbox */ 5419 WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value); 5420 WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb1), word0); 5421 5422 /* interrupt board to do it right away */ 5423 WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 5424 5425 /* First wait for command acceptence */ 5426 j = 0; 5427 while (j++ < 1000) { 5428 value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); 5429 5430 if (value == 0xAAAAAAAA) { 5431 break; 5432 } 5433 5434 DELAYUS(50); 5435 } 5436 5437 if (value == 0xAAAAAAAA) { 5438 /* Now wait for mailbox ownership to clear */ 5439 while (j++ < 10000) { 5440 word0 = 5441 READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1)); 5442 5443 if (swpmb->mbxOwner == 0) { 5444 break; 5445 } 5446 5447 DELAYUS(50); 5448 } 5449 5450 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5451 "Interlock succeeded."); 5452 5453 goto done; 5454 } 5455 5456 /* Interlock failed !!! */ 5457 5458 /* If this is the first time then try again */ 5459 if (interlock_failed == 0) { 5460 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5461 "Interlock failed. Retrying..."); 5462 5463 /* Try again */ 5464 interlock_failed = 1; 5465 goto interlock_B; 5466 } 5467 5468 /* 5469 * Now check for error attention to indicate the board has 5470 * been kiilled 5471 */ 5472 j = 0; 5473 while (j++ < 10000) { 5474 ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba)); 5475 5476 if (ha_copy & HA_ERATT) { 5477 break; 5478 } 5479 5480 DELAYUS(50); 5481 } 5482 5483 if (ha_copy & HA_ERATT) { 5484 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5485 "Interlock failed. Board killed."); 5486 } else { 5487 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5488 "Interlock failed. Board not killed."); 5489 } 5490 5491 done: 5492 5493 hba->mbox_queue_flag = 0; 5494 5495 EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 5496 5497 #ifdef FMA_SUPPORT 5498 /* Access handle validation */ 5499 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 5500 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 5501 #endif /* FMA_SUPPORT */ 5502 5503 mutex_exit(&EMLXS_PORT_LOCK); 5504 5505 return; 5506 5507 } /* emlxs_sli3_hba_kill() */ 5508 5509 5510 static void 5511 emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba) 5512 { 5513 emlxs_port_t *port = &PPORT; 5514 MAILBOX *swpmb; 5515 MAILBOX *mb2; 5516 MAILBOX *mb1; 5517 uint32_t word0; 5518 off_t offset; 5519 uint32_t j; 5520 uint32_t value; 5521 uint32_t size; 5522 5523 /* Disable all host interrupts */ 5524 hba->sli.sli3.hc_copy = 0; 5525 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 5526 WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff); 5527 5528 mb2 = FC_SLIM2_MAILBOX(hba); 5529 mb1 = FC_SLIM1_MAILBOX(hba); 5530 swpmb = (MAILBOX *)&word0; 5531 5532 value = 0x55555555; 5533 word0 = 0; 5534 swpmb->mbxCommand = MBX_KILL_BOARD; 5535 swpmb->mbxOwner = OWN_CHIP; 5536 5537 /* Write value to SLIM */ 5538 WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value); 5539 WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0); 5540 5541 /* Send Kill board request */ 5542 mb2->un.varWords[0] = value; 5543 mb2->mbxCommand = MBX_KILL_BOARD; 5544 mb2->mbxOwner = OWN_CHIP; 5545 5546 /* Sync the memory */ 5547 offset = (off_t)((uint64_t)((unsigned long)mb2) 5548 - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5549 size = (sizeof (uint32_t) * 2); 5550 5551 BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size); 5552 5553 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size, 5554 DDI_DMA_SYNC_FORDEV); 5555 5556 /* interrupt board to do it right away */ 5557 WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 5558 5559 /* First wait for command acceptence */ 5560 j = 0; 5561 while (j++ < 1000) { 5562 value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); 5563 5564 if (value == 0xAAAAAAAA) { 5565 break; 5566 } 5567 DELAYUS(50); 5568 } 5569 if (value == 0xAAAAAAAA) { 5570 /* Now wait for mailbox ownership to clear */ 5571 while (j++ < 10000) { 5572 word0 = 5573 READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1)); 5574 if (swpmb->mbxOwner == 0) { 5575 break; 5576 } 5577 DELAYUS(50); 5578 } 5579 goto done; 5580 } 5581 5582 done: 5583 EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 5584 5585 #ifdef FMA_SUPPORT 5586 /* Access handle validation */ 5587 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 5588 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 5589 #endif /* FMA_SUPPORT */ 5590 return; 5591 5592 } /* emlxs_sli3_hba_kill4quiesce */ 5593 5594 5595 5596 5597 /* 5598 * emlxs_handle_mb_event 5599 * 5600 * Description: Process a Mailbox Attention. 5601 * Called from host_interrupt to process MBATT 5602 * 5603 * Returns: 5604 * 5605 */ 5606 static uint32_t 5607 emlxs_handle_mb_event(emlxs_hba_t *hba) 5608 { 5609 emlxs_port_t *port = &PPORT; 5610 MAILBOX *mb; 5611 MAILBOX *swpmb; 5612 MAILBOX *mbox; 5613 MAILBOXQ *mbq = NULL; 5614 volatile uint32_t word0; 5615 MATCHMAP *mbox_bp; 5616 off_t offset; 5617 uint32_t i; 5618 int rc; 5619 5620 swpmb = (MAILBOX *)&word0; 5621 5622 mutex_enter(&EMLXS_PORT_LOCK); 5623 switch (hba->mbox_queue_flag) { 5624 case 0: 5625 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg, 5626 "No mailbox active."); 5627 5628 mutex_exit(&EMLXS_PORT_LOCK); 5629 return (0); 5630 5631 case MBX_POLL: 5632 5633 /* Mark mailbox complete, this should wake up any polling */ 5634 /* threads. This can happen if interrupts are enabled while */ 5635 /* a polled mailbox command is outstanding. If we don't set */ 5636 /* MBQ_COMPLETED here, the polling thread may wait until */ 5637 /* timeout error occurs */ 5638 5639 mutex_enter(&EMLXS_MBOX_LOCK); 5640 mbq = (MAILBOXQ *)hba->mbox_mbq; 5641 if (mbq) { 5642 port = (emlxs_port_t *)mbq->port; 5643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5644 "Mailbox event. Completing Polled command."); 5645 mbq->flag |= MBQ_COMPLETED; 5646 } 5647 mutex_exit(&EMLXS_MBOX_LOCK); 5648 5649 mutex_exit(&EMLXS_PORT_LOCK); 5650 return (0); 5651 5652 case MBX_SLEEP: 5653 case MBX_NOWAIT: 5654 /* Check mbox_timer, it acts as a service flag too */ 5655 /* The first to service the mbox queue will clear the timer */ 5656 if (hba->mbox_timer) { 5657 hba->mbox_timer = 0; 5658 5659 mutex_enter(&EMLXS_MBOX_LOCK); 5660 mbq = (MAILBOXQ *)hba->mbox_mbq; 5661 mutex_exit(&EMLXS_MBOX_LOCK); 5662 } 5663 5664 if (!mbq) { 5665 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5666 "Mailbox event. No service required."); 5667 mutex_exit(&EMLXS_PORT_LOCK); 5668 return (0); 5669 } 5670 5671 mb = (MAILBOX *)mbq; 5672 mutex_exit(&EMLXS_PORT_LOCK); 5673 break; 5674 5675 default: 5676 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg, 5677 "Invalid Mailbox flag (%x)."); 5678 5679 mutex_exit(&EMLXS_PORT_LOCK); 5680 return (0); 5681 } 5682 5683 /* Set port context */ 5684 port = (emlxs_port_t *)mbq->port; 5685 5686 /* Get first word of mailbox */ 5687 if (hba->flag & FC_SLIM2_MODE) { 5688 mbox = FC_SLIM2_MAILBOX(hba); 5689 offset = (off_t)((uint64_t)((unsigned long)mbox) 5690 - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5691 5692 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 5693 sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 5694 word0 = *((volatile uint32_t *)mbox); 5695 word0 = BE_SWAP32(word0); 5696 } else { 5697 mbox = FC_SLIM1_MAILBOX(hba); 5698 word0 = READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); 5699 } 5700 5701 i = 0; 5702 while (swpmb->mbxOwner == OWN_CHIP) { 5703 if (i++ > 10000) { 5704 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg, 5705 "OWN_CHIP: %s: status=%x", 5706 emlxs_mb_cmd_xlate(swpmb->mbxCommand), 5707 swpmb->mbxStatus); 5708 5709 return (1); 5710 } 5711 5712 /* Get first word of mailbox */ 5713 if (hba->flag & FC_SLIM2_MODE) { 5714 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 5715 offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 5716 word0 = *((volatile uint32_t *)mbox); 5717 word0 = BE_SWAP32(word0); 5718 } else { 5719 word0 = 5720 READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); 5721 } 5722 } 5723 5724 /* Now that we are the owner, DMA Sync entire mailbox if needed */ 5725 if (hba->flag & FC_SLIM2_MODE) { 5726 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 5727 MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL); 5728 5729 BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb, 5730 MAILBOX_CMD_BSIZE); 5731 } else { 5732 READ_SLIM_COPY(hba, (uint32_t *)mb, (uint32_t *)mbox, 5733 MAILBOX_CMD_WSIZE); 5734 } 5735 5736 #ifdef MBOX_EXT_SUPPORT 5737 if (mbq->extbuf) { 5738 uint32_t *mbox_ext = 5739 (uint32_t *)((uint8_t *)mbox + MBOX_EXTENSION_OFFSET); 5740 off_t offset_ext = offset + MBOX_EXTENSION_OFFSET; 5741 5742 if (hba->flag & FC_SLIM2_MODE) { 5743 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 5744 offset_ext, mbq->extsize, 5745 DDI_DMA_SYNC_FORKERNEL); 5746 BE_SWAP32_BCOPY((uint8_t *)mbox_ext, 5747 (uint8_t *)mbq->extbuf, mbq->extsize); 5748 } else { 5749 READ_SLIM_COPY(hba, (uint32_t *)mbq->extbuf, 5750 mbox_ext, (mbq->extsize / 4)); 5751 } 5752 } 5753 #endif /* MBOX_EXT_SUPPORT */ 5754 5755 #ifdef FMA_SUPPORT 5756 if (!(hba->flag & FC_SLIM2_MODE)) { 5757 /* Access handle validation */ 5758 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 5759 } 5760 #endif /* FMA_SUPPORT */ 5761 5762 /* Now sync the memory buffer if one was used */ 5763 if (mbq->bp) { 5764 mbox_bp = (MATCHMAP *)mbq->bp; 5765 EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size, 5766 DDI_DMA_SYNC_FORKERNEL); 5767 } 5768 5769 /* Mailbox has been completely received at this point */ 5770 5771 if (mb->mbxCommand == MBX_HEARTBEAT) { 5772 hba->heartbeat_active = 0; 5773 goto done; 5774 } 5775 5776 if (hba->mbox_queue_flag == MBX_SLEEP) { 5777 if (swpmb->mbxCommand != MBX_DOWN_LOAD && 5778 swpmb->mbxCommand != MBX_DUMP_MEMORY) { 5779 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5780 "Received. %s: status=%x Sleep.", 5781 emlxs_mb_cmd_xlate(swpmb->mbxCommand), 5782 swpmb->mbxStatus); 5783 } 5784 } else { 5785 if (swpmb->mbxCommand != MBX_DOWN_LOAD && 5786 swpmb->mbxCommand != MBX_DUMP_MEMORY) { 5787 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5788 "Completed. %s: status=%x", 5789 emlxs_mb_cmd_xlate(swpmb->mbxCommand), 5790 swpmb->mbxStatus); 5791 } 5792 } 5793 5794 /* Filter out passthru mailbox */ 5795 if (mbq->flag & MBQ_PASSTHRU) { 5796 goto done; 5797 } 5798 5799 if (mb->mbxStatus) { 5800 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5801 "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand), 5802 (uint32_t)mb->mbxStatus); 5803 } 5804 5805 if (mbq->mbox_cmpl) { 5806 rc = (mbq->mbox_cmpl)(hba, mbq); 5807 /* If mbox was retried, return immediately */ 5808 if (rc) { 5809 return (0); 5810 } 5811 } 5812 5813 done: 5814 5815 /* Clean up the mailbox area */ 5816 emlxs_mb_fini(hba, mb, mb->mbxStatus); 5817 5818 mbq = (MAILBOXQ *)emlxs_mb_get(hba); 5819 if (mbq) { 5820 /* Attempt to send pending mailboxes */ 5821 rc = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 5822 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 5823 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 5824 } 5825 } 5826 return (0); 5827 5828 } /* emlxs_handle_mb_event() */ 5829 5830 5831 extern void 5832 emlxs_sli3_timer(emlxs_hba_t *hba) 5833 { 5834 /* Perform SLI3 level timer checks */ 5835 5836 emlxs_sli3_timer_check_mbox(hba); 5837 5838 } /* emlxs_sli3_timer() */ 5839 5840 5841 static void 5842 emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba) 5843 { 5844 emlxs_port_t *port = &PPORT; 5845 emlxs_config_t *cfg = &CFG; 5846 MAILBOX *mb = NULL; 5847 uint32_t word0; 5848 uint32_t offset; 5849 uint32_t ha_copy = 0; 5850 5851 if (!cfg[CFG_TIMEOUT_ENABLE].current) { 5852 return; 5853 } 5854 5855 mutex_enter(&EMLXS_PORT_LOCK); 5856 5857 /* Return if timer hasn't expired */ 5858 if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) { 5859 mutex_exit(&EMLXS_PORT_LOCK); 5860 return; 5861 } 5862 5863 /* Mailbox timed out, first check for error attention */ 5864 ha_copy = emlxs_check_attention(hba); 5865 5866 if (ha_copy & HA_ERATT) { 5867 hba->mbox_timer = 0; 5868 mutex_exit(&EMLXS_PORT_LOCK); 5869 emlxs_handle_ff_error(hba); 5870 return; 5871 } 5872 5873 if (hba->mbox_queue_flag) { 5874 /* Get first word of mailbox */ 5875 if (hba->flag & FC_SLIM2_MODE) { 5876 mb = FC_SLIM2_MAILBOX(hba); 5877 offset = 5878 (off_t)((uint64_t)((unsigned long)mb) - (uint64_t) 5879 ((unsigned long)hba->sli.sli3.slim2.virt)); 5880 5881 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 5882 offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 5883 word0 = *((volatile uint32_t *)mb); 5884 word0 = BE_SWAP32(word0); 5885 } else { 5886 mb = FC_SLIM1_MAILBOX(hba); 5887 word0 = 5888 READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb)); 5889 #ifdef FMA_SUPPORT 5890 /* Access handle validation */ 5891 EMLXS_CHK_ACC_HANDLE(hba, 5892 hba->sli.sli3.slim_acc_handle); 5893 #endif /* FMA_SUPPORT */ 5894 } 5895 5896 mb = (MAILBOX *)&word0; 5897 5898 /* Check if mailbox has actually completed */ 5899 if (mb->mbxOwner == OWN_HOST) { 5900 /* Read host attention register to determine */ 5901 /* interrupt source */ 5902 uint32_t ha_copy = emlxs_check_attention(hba); 5903 5904 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5905 "Mailbox attention missed: %s. Forcing event. " 5906 "hc=%x ha=%x", emlxs_mb_cmd_xlate(mb->mbxCommand), 5907 hba->sli.sli3.hc_copy, ha_copy); 5908 5909 mutex_exit(&EMLXS_PORT_LOCK); 5910 5911 (void) emlxs_handle_mb_event(hba); 5912 5913 return; 5914 } 5915 5916 /* The first to service the mbox queue will clear the timer */ 5917 /* We will service the mailbox here */ 5918 hba->mbox_timer = 0; 5919 5920 mutex_enter(&EMLXS_MBOX_LOCK); 5921 mb = (MAILBOX *)hba->mbox_mbq; 5922 mutex_exit(&EMLXS_MBOX_LOCK); 5923 } 5924 5925 if (mb) { 5926 switch (hba->mbox_queue_flag) { 5927 case MBX_NOWAIT: 5928 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 5929 "%s: Nowait.", 5930 emlxs_mb_cmd_xlate(mb->mbxCommand)); 5931 break; 5932 5933 case MBX_SLEEP: 5934 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 5935 "%s: mb=%p Sleep.", 5936 emlxs_mb_cmd_xlate(mb->mbxCommand), 5937 mb); 5938 break; 5939 5940 case MBX_POLL: 5941 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 5942 "%s: mb=%p Polled.", 5943 emlxs_mb_cmd_xlate(mb->mbxCommand), 5944 mb); 5945 break; 5946 5947 default: 5948 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 5949 "%s: mb=%p (%d).", 5950 emlxs_mb_cmd_xlate(mb->mbxCommand), 5951 mb, hba->mbox_queue_flag); 5952 break; 5953 } 5954 } else { 5955 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL); 5956 } 5957 5958 hba->flag |= FC_MBOX_TIMEOUT; 5959 EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR); 5960 5961 mutex_exit(&EMLXS_PORT_LOCK); 5962 5963 /* Perform mailbox cleanup */ 5964 /* This will wake any sleeping or polling threads */ 5965 emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 5966 5967 /* Trigger adapter shutdown */ 5968 emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); 5969 5970 return; 5971 5972 } /* emlxs_sli3_timer_check_mbox() */ 5973 5974 5975 /* 5976 * emlxs_mb_config_port Issue a CONFIG_PORT mailbox command 5977 */ 5978 static uint32_t 5979 emlxs_mb_config_port(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t sli_mode, 5980 uint32_t hbainit) 5981 { 5982 MAILBOX *mb = (MAILBOX *)mbq; 5983 emlxs_vpd_t *vpd = &VPD; 5984 emlxs_port_t *port = &PPORT; 5985 emlxs_config_t *cfg; 5986 RING *rp; 5987 uint64_t pcb; 5988 uint64_t mbx; 5989 uint64_t hgp; 5990 uint64_t pgp; 5991 uint64_t rgp; 5992 MAILBOX *mbox; 5993 SLIM2 *slim; 5994 SLI2_RDSC *rdsc; 5995 uint64_t offset; 5996 uint32_t Laddr; 5997 uint32_t i; 5998 5999 cfg = &CFG; 6000 bzero((void *)mb, MAILBOX_CMD_BSIZE); 6001 mbox = NULL; 6002 slim = NULL; 6003 6004 mb->mbxCommand = MBX_CONFIG_PORT; 6005 mb->mbxOwner = OWN_HOST; 6006 mbq->mbox_cmpl = NULL; 6007 6008 mb->un.varCfgPort.pcbLen = sizeof (PCB); 6009 mb->un.varCfgPort.hbainit[0] = hbainit; 6010 6011 pcb = hba->sli.sli3.slim2.phys + 6012 (uint64_t)((unsigned long)&(slim->pcb)); 6013 mb->un.varCfgPort.pcbLow = PADDR_LO(pcb); 6014 mb->un.varCfgPort.pcbHigh = PADDR_HI(pcb); 6015 6016 /* Set Host pointers in SLIM flag */ 6017 mb->un.varCfgPort.hps = 1; 6018 6019 /* Initialize hba structure for assumed default SLI2 mode */ 6020 /* If config port succeeds, then we will update it then */ 6021 hba->sli_mode = sli_mode; 6022 hba->vpi_max = 0; 6023 hba->flag &= ~FC_NPIV_ENABLED; 6024 6025 if (sli_mode == EMLXS_HBA_SLI3_MODE) { 6026 mb->un.varCfgPort.sli_mode = EMLXS_HBA_SLI3_MODE; 6027 mb->un.varCfgPort.cerbm = 1; 6028 mb->un.varCfgPort.max_hbq = EMLXS_NUM_HBQ; 6029 6030 if (cfg[CFG_NPIV_ENABLE].current) { 6031 if (vpd->feaLevelHigh >= 0x09) { 6032 if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 6033 mb->un.varCfgPort.vpi_max = 6034 MAX_VPORTS - 1; 6035 } else { 6036 mb->un.varCfgPort.vpi_max = 6037 MAX_VPORTS_LIMITED - 1; 6038 } 6039 6040 mb->un.varCfgPort.cmv = 1; 6041 } else { 6042 EMLXS_MSGF(EMLXS_CONTEXT, 6043 &emlxs_init_debug_msg, 6044 "CFGPORT: Firmware does not support NPIV. " 6045 "level=%d", vpd->feaLevelHigh); 6046 } 6047 6048 } 6049 } 6050 6051 /* 6052 * Now setup pcb 6053 */ 6054 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.type = TYPE_NATIVE_SLI2; 6055 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.feature = FEATURE_INITIAL_SLI2; 6056 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.maxRing = 6057 (hba->sli.sli3.ring_count - 1); 6058 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mailBoxSize = 6059 sizeof (MAILBOX) + MBOX_EXTENSION_SIZE; 6060 6061 mbx = hba->sli.sli3.slim2.phys + 6062 (uint64_t)((unsigned long)&(slim->mbx)); 6063 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrHigh = PADDR_HI(mbx); 6064 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrLow = PADDR_LO(mbx); 6065 6066 6067 /* 6068 * Set up HGP - Port Memory 6069 * 6070 * CR0Put - SLI2(no HBQs) = 0xc0, With HBQs = 0x80 6071 * RR0Get 0xc4 0x84 6072 * CR1Put 0xc8 0x88 6073 * RR1Get 0xcc 0x8c 6074 * CR2Put 0xd0 0x90 6075 * RR2Get 0xd4 0x94 6076 * CR3Put 0xd8 0x98 6077 * RR3Get 0xdc 0x9c 6078 * 6079 * Reserved 0xa0-0xbf 6080 * 6081 * If HBQs configured: 6082 * HBQ 0 Put ptr 0xc0 6083 * HBQ 1 Put ptr 0xc4 6084 * HBQ 2 Put ptr 0xc8 6085 * ... 6086 * HBQ(M-1)Put Pointer 0xc0+(M-1)*4 6087 */ 6088 6089 if (sli_mode >= EMLXS_HBA_SLI3_MODE) { 6090 /* ERBM is enabled */ 6091 hba->sli.sli3.hgp_ring_offset = 0x80; 6092 hba->sli.sli3.hgp_hbq_offset = 0xC0; 6093 6094 hba->sli.sli3.iocb_cmd_size = SLI3_IOCB_CMD_SIZE; 6095 hba->sli.sli3.iocb_rsp_size = SLI3_IOCB_RSP_SIZE; 6096 6097 } else { /* SLI2 */ 6098 /* ERBM is disabled */ 6099 hba->sli.sli3.hgp_ring_offset = 0xC0; 6100 hba->sli.sli3.hgp_hbq_offset = 0; 6101 6102 hba->sli.sli3.iocb_cmd_size = SLI2_IOCB_CMD_SIZE; 6103 hba->sli.sli3.iocb_rsp_size = SLI2_IOCB_RSP_SIZE; 6104 } 6105 6106 /* The Sbus card uses Host Memory. The PCI card uses SLIM POINTER */ 6107 if (hba->bus_type == SBUS_FC) { 6108 hgp = hba->sli.sli3.slim2.phys + 6109 (uint64_t)((unsigned long)&(mbox->us.s2.host)); 6110 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh = 6111 PADDR_HI(hgp); 6112 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow = 6113 PADDR_LO(hgp); 6114 } else { 6115 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh = 6116 (uint32_t)ddi_get32(hba->pci_acc_handle, 6117 (uint32_t *)(hba->pci_addr + PCI_BAR_1_REGISTER)); 6118 6119 Laddr = 6120 ddi_get32(hba->pci_acc_handle, 6121 (uint32_t *)(hba->pci_addr + PCI_BAR_0_REGISTER)); 6122 Laddr &= ~0x4; 6123 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow = 6124 (uint32_t)(Laddr + hba->sli.sli3.hgp_ring_offset); 6125 6126 #ifdef FMA_SUPPORT 6127 /* Access handle validation */ 6128 EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle); 6129 #endif /* FMA_SUPPORT */ 6130 6131 } 6132 6133 pgp = hba->sli.sli3.slim2.phys + 6134 (uint64_t)((unsigned long)&(mbox->us.s2.port)); 6135 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrHigh = 6136 PADDR_HI(pgp); 6137 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrLow = 6138 PADDR_LO(pgp); 6139 6140 offset = 0; 6141 for (i = 0; i < 4; i++) { 6142 rp = &hba->sli.sli3.ring[i]; 6143 rdsc = &((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.rdsc[i]; 6144 6145 /* Setup command ring */ 6146 rgp = hba->sli.sli3.slim2.phys + 6147 (uint64_t)((unsigned long)&(slim->IOCBs[offset])); 6148 rdsc->cmdAddrHigh = PADDR_HI(rgp); 6149 rdsc->cmdAddrLow = PADDR_LO(rgp); 6150 rdsc->cmdEntries = rp->fc_numCiocb; 6151 6152 rp->fc_cmdringaddr = 6153 (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset]; 6154 offset += rdsc->cmdEntries * hba->sli.sli3.iocb_cmd_size; 6155 6156 /* Setup response ring */ 6157 rgp = hba->sli.sli3.slim2.phys + 6158 (uint64_t)((unsigned long)&(slim->IOCBs[offset])); 6159 rdsc->rspAddrHigh = PADDR_HI(rgp); 6160 rdsc->rspAddrLow = PADDR_LO(rgp); 6161 rdsc->rspEntries = rp->fc_numRiocb; 6162 6163 rp->fc_rspringaddr = 6164 (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset]; 6165 offset += rdsc->rspEntries * hba->sli.sli3.iocb_rsp_size; 6166 } 6167 6168 BE_SWAP32_BCOPY((uint8_t *) 6169 (&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb), 6170 (uint8_t *)(&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb), 6171 sizeof (PCB)); 6172 6173 offset = ((uint64_t)((unsigned long) 6174 &(((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb)) - 6175 (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 6176 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, (off_t)offset, 6177 sizeof (PCB), DDI_DMA_SYNC_FORDEV); 6178 6179 return (0); 6180 6181 } /* emlxs_mb_config_port() */ 6182 6183 6184 static uint32_t 6185 emlxs_hbq_setup(emlxs_hba_t *hba, uint32_t hbq_id) 6186 { 6187 emlxs_port_t *port = &PPORT; 6188 HBQ_INIT_t *hbq; 6189 MATCHMAP *mp; 6190 HBQE_t *hbqE; 6191 MAILBOX *mb; 6192 MAILBOXQ *mbq; 6193 void *ioa2; 6194 uint32_t j; 6195 uint32_t count; 6196 uint32_t size; 6197 uint32_t ringno; 6198 uint32_t seg; 6199 6200 switch (hbq_id) { 6201 case EMLXS_ELS_HBQ_ID: 6202 count = MEM_ELSBUF_COUNT; 6203 size = MEM_ELSBUF_SIZE; 6204 ringno = FC_ELS_RING; 6205 seg = MEM_ELSBUF; 6206 HBASTATS.ElsUbPosted = count; 6207 break; 6208 6209 case EMLXS_IP_HBQ_ID: 6210 count = MEM_IPBUF_COUNT; 6211 size = MEM_IPBUF_SIZE; 6212 ringno = FC_IP_RING; 6213 seg = MEM_IPBUF; 6214 HBASTATS.IpUbPosted = count; 6215 break; 6216 6217 case EMLXS_CT_HBQ_ID: 6218 count = MEM_CTBUF_COUNT; 6219 size = MEM_CTBUF_SIZE; 6220 ringno = FC_CT_RING; 6221 seg = MEM_CTBUF; 6222 HBASTATS.CtUbPosted = count; 6223 break; 6224 6225 #ifdef SFCT_SUPPORT 6226 case EMLXS_FCT_HBQ_ID: 6227 count = MEM_FCTBUF_COUNT; 6228 size = MEM_FCTBUF_SIZE; 6229 ringno = FC_FCT_RING; 6230 seg = MEM_FCTBUF; 6231 HBASTATS.FctUbPosted = count; 6232 break; 6233 #endif /* SFCT_SUPPORT */ 6234 6235 default: 6236 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6237 "emlxs_hbq_setup: Invalid HBQ id. (%x)", hbq_id); 6238 return (1); 6239 } 6240 6241 /* Configure HBQ */ 6242 hbq = &hba->sli.sli3.hbq_table[hbq_id]; 6243 hbq->HBQ_numEntries = count; 6244 6245 /* Get a Mailbox buffer to setup mailbox commands for CONFIG_HBQ */ 6246 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) { 6247 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6248 "emlxs_hbq_setup: Unable to get mailbox."); 6249 return (1); 6250 } 6251 mb = (MAILBOX *)mbq; 6252 6253 /* Allocate HBQ Host buffer and Initialize the HBQEs */ 6254 if (emlxs_hbq_alloc(hba, hbq_id)) { 6255 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6256 "emlxs_hbq_setup: Unable to allocate HBQ."); 6257 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 6258 return (1); 6259 } 6260 6261 hbq->HBQ_recvNotify = 1; 6262 hbq->HBQ_num_mask = 0; /* Bind to ring */ 6263 hbq->HBQ_profile = 0; /* Selection profile */ 6264 /* 0=all, 7=logentry */ 6265 hbq->HBQ_ringMask = 1 << ringno; /* b0100 * ringno - Binds */ 6266 /* HBQ to a ring */ 6267 /* Ring0=b0001, Ring1=b0010, */ 6268 /* Ring2=b0100 */ 6269 hbq->HBQ_headerLen = 0; /* 0 if not profile 4 or 5 */ 6270 hbq->HBQ_logEntry = 0; /* Set to 1 if this HBQ will */ 6271 /* be used for */ 6272 hbq->HBQ_id = hbq_id; 6273 hbq->HBQ_PutIdx_next = 0; 6274 hbq->HBQ_PutIdx = hbq->HBQ_numEntries - 1; 6275 hbq->HBQ_GetIdx = 0; 6276 hbq->HBQ_PostBufCnt = hbq->HBQ_numEntries; 6277 bzero(hbq->HBQ_PostBufs, sizeof (hbq->HBQ_PostBufs)); 6278 6279 /* Fill in POST BUFFERs in HBQE */ 6280 hbqE = (HBQE_t *)hbq->HBQ_host_buf.virt; 6281 for (j = 0; j < hbq->HBQ_numEntries; j++, hbqE++) { 6282 /* Allocate buffer to post */ 6283 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, 6284 seg, 1)) == 0) { 6285 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6286 "emlxs_hbq_setup: Unable to allocate HBQ buffer. " 6287 "cnt=%d", j); 6288 emlxs_hbq_free_all(hba, hbq_id); 6289 return (1); 6290 } 6291 6292 hbq->HBQ_PostBufs[j] = mp; 6293 6294 hbqE->unt.ext.HBQ_tag = hbq_id; 6295 hbqE->unt.ext.HBQE_tag = j; 6296 hbqE->bde.tus.f.bdeSize = size; 6297 hbqE->bde.tus.f.bdeFlags = 0; 6298 hbqE->unt.w = BE_SWAP32(hbqE->unt.w); 6299 hbqE->bde.tus.w = BE_SWAP32(hbqE->bde.tus.w); 6300 hbqE->bde.addrLow = 6301 BE_SWAP32(PADDR_LO(mp->phys)); 6302 hbqE->bde.addrHigh = 6303 BE_SWAP32(PADDR_HI(mp->phys)); 6304 } 6305 6306 /* Issue CONFIG_HBQ */ 6307 emlxs_mb_config_hbq(hba, mbq, hbq_id); 6308 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 6309 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 6310 "emlxs_hbq_setup: Unable to config HBQ. cmd=%x status=%x", 6311 mb->mbxCommand, mb->mbxStatus); 6312 6313 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 6314 emlxs_hbq_free_all(hba, hbq_id); 6315 return (1); 6316 } 6317 6318 /* Setup HBQ Get/Put indexes */ 6319 ioa2 = (void *)((char *)hba->sli.sli3.slim_addr + 6320 (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t)))); 6321 WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, hbq->HBQ_PutIdx); 6322 6323 hba->sli.sli3.hbq_count++; 6324 6325 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 6326 6327 #ifdef FMA_SUPPORT 6328 /* Access handle validation */ 6329 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 6330 != DDI_FM_OK) { 6331 EMLXS_MSGF(EMLXS_CONTEXT, 6332 &emlxs_invalid_access_handle_msg, NULL); 6333 emlxs_hbq_free_all(hba, hbq_id); 6334 return (1); 6335 } 6336 #endif /* FMA_SUPPORT */ 6337 6338 return (0); 6339 6340 } /* emlxs_hbq_setup() */ 6341 6342 6343 extern void 6344 emlxs_hbq_free_all(emlxs_hba_t *hba, uint32_t hbq_id) 6345 { 6346 HBQ_INIT_t *hbq; 6347 MBUF_INFO *buf_info; 6348 MBUF_INFO bufinfo; 6349 uint32_t seg; 6350 uint32_t j; 6351 6352 switch (hbq_id) { 6353 case EMLXS_ELS_HBQ_ID: 6354 seg = MEM_ELSBUF; 6355 HBASTATS.ElsUbPosted = 0; 6356 break; 6357 6358 case EMLXS_IP_HBQ_ID: 6359 seg = MEM_IPBUF; 6360 HBASTATS.IpUbPosted = 0; 6361 break; 6362 6363 case EMLXS_CT_HBQ_ID: 6364 seg = MEM_CTBUF; 6365 HBASTATS.CtUbPosted = 0; 6366 break; 6367 6368 #ifdef SFCT_SUPPORT 6369 case EMLXS_FCT_HBQ_ID: 6370 seg = MEM_FCTBUF; 6371 HBASTATS.FctUbPosted = 0; 6372 break; 6373 #endif /* SFCT_SUPPORT */ 6374 6375 default: 6376 return; 6377 } 6378 6379 6380 hbq = &hba->sli.sli3.hbq_table[hbq_id]; 6381 6382 if (hbq->HBQ_host_buf.virt != 0) { 6383 for (j = 0; j < hbq->HBQ_PostBufCnt; j++) { 6384 emlxs_mem_put(hba, seg, 6385 (void *)hbq->HBQ_PostBufs[j]); 6386 hbq->HBQ_PostBufs[j] = NULL; 6387 } 6388 hbq->HBQ_PostBufCnt = 0; 6389 6390 buf_info = &bufinfo; 6391 bzero(buf_info, sizeof (MBUF_INFO)); 6392 6393 buf_info->size = hbq->HBQ_host_buf.size; 6394 buf_info->virt = hbq->HBQ_host_buf.virt; 6395 buf_info->phys = hbq->HBQ_host_buf.phys; 6396 buf_info->dma_handle = hbq->HBQ_host_buf.dma_handle; 6397 buf_info->data_handle = hbq->HBQ_host_buf.data_handle; 6398 buf_info->flags = FC_MBUF_DMA; 6399 6400 emlxs_mem_free(hba, buf_info); 6401 6402 hbq->HBQ_host_buf.virt = NULL; 6403 } 6404 6405 return; 6406 6407 } /* emlxs_hbq_free_all() */ 6408 6409 6410 extern void 6411 emlxs_update_HBQ_index(emlxs_hba_t *hba, uint32_t hbq_id) 6412 { 6413 #ifdef FMA_SUPPORT 6414 emlxs_port_t *port = &PPORT; 6415 #endif /* FMA_SUPPORT */ 6416 void *ioa2; 6417 uint32_t status; 6418 uint32_t HBQ_PortGetIdx; 6419 HBQ_INIT_t *hbq; 6420 6421 switch (hbq_id) { 6422 case EMLXS_ELS_HBQ_ID: 6423 HBASTATS.ElsUbPosted++; 6424 break; 6425 6426 case EMLXS_IP_HBQ_ID: 6427 HBASTATS.IpUbPosted++; 6428 break; 6429 6430 case EMLXS_CT_HBQ_ID: 6431 HBASTATS.CtUbPosted++; 6432 break; 6433 6434 #ifdef SFCT_SUPPORT 6435 case EMLXS_FCT_HBQ_ID: 6436 HBASTATS.FctUbPosted++; 6437 break; 6438 #endif /* SFCT_SUPPORT */ 6439 6440 default: 6441 return; 6442 } 6443 6444 hbq = &hba->sli.sli3.hbq_table[hbq_id]; 6445 6446 hbq->HBQ_PutIdx = 6447 (hbq->HBQ_PutIdx + 1 >= 6448 hbq->HBQ_numEntries) ? 0 : hbq->HBQ_PutIdx + 1; 6449 6450 if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) { 6451 HBQ_PortGetIdx = 6452 BE_SWAP32(((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2. 6453 HBQ_PortGetIdx[hbq_id]); 6454 6455 hbq->HBQ_GetIdx = HBQ_PortGetIdx; 6456 6457 if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) { 6458 return; 6459 } 6460 } 6461 6462 ioa2 = (void *)((char *)hba->sli.sli3.slim_addr + 6463 (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t)))); 6464 status = hbq->HBQ_PutIdx; 6465 WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, status); 6466 6467 #ifdef FMA_SUPPORT 6468 /* Access handle validation */ 6469 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 6470 #endif /* FMA_SUPPORT */ 6471 6472 return; 6473 6474 } /* emlxs_update_HBQ_index() */ 6475 6476 6477 static void 6478 emlxs_sli3_enable_intr(emlxs_hba_t *hba) 6479 { 6480 #ifdef FMA_SUPPORT 6481 emlxs_port_t *port = &PPORT; 6482 #endif /* FMA_SUPPORT */ 6483 uint32_t status; 6484 6485 /* Enable mailbox, error attention interrupts */ 6486 status = (uint32_t)(HC_MBINT_ENA); 6487 6488 /* Enable ring interrupts */ 6489 if (hba->sli.sli3.ring_count >= 4) { 6490 status |= 6491 (HC_R3INT_ENA | HC_R2INT_ENA | HC_R1INT_ENA | 6492 HC_R0INT_ENA); 6493 } else if (hba->sli.sli3.ring_count == 3) { 6494 status |= (HC_R2INT_ENA | HC_R1INT_ENA | HC_R0INT_ENA); 6495 } else if (hba->sli.sli3.ring_count == 2) { 6496 status |= (HC_R1INT_ENA | HC_R0INT_ENA); 6497 } else if (hba->sli.sli3.ring_count == 1) { 6498 status |= (HC_R0INT_ENA); 6499 } 6500 6501 hba->sli.sli3.hc_copy = status; 6502 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 6503 6504 #ifdef FMA_SUPPORT 6505 /* Access handle validation */ 6506 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 6507 #endif /* FMA_SUPPORT */ 6508 6509 } /* emlxs_sli3_enable_intr() */ 6510 6511 6512 static void 6513 emlxs_enable_latt(emlxs_hba_t *hba) 6514 { 6515 #ifdef FMA_SUPPORT 6516 emlxs_port_t *port = &PPORT; 6517 #endif /* FMA_SUPPORT */ 6518 6519 mutex_enter(&EMLXS_PORT_LOCK); 6520 hba->sli.sli3.hc_copy |= HC_LAINT_ENA; 6521 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 6522 #ifdef FMA_SUPPORT 6523 /* Access handle validation */ 6524 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 6525 #endif /* FMA_SUPPORT */ 6526 mutex_exit(&EMLXS_PORT_LOCK); 6527 6528 } /* emlxs_enable_latt() */ 6529 6530 6531 static void 6532 emlxs_sli3_disable_intr(emlxs_hba_t *hba, uint32_t att) 6533 { 6534 #ifdef FMA_SUPPORT 6535 emlxs_port_t *port = &PPORT; 6536 #endif /* FMA_SUPPORT */ 6537 6538 /* Disable all adapter interrupts */ 6539 hba->sli.sli3.hc_copy = att; 6540 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 6541 #ifdef FMA_SUPPORT 6542 /* Access handle validation */ 6543 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 6544 #endif /* FMA_SUPPORT */ 6545 6546 } /* emlxs_sli3_disable_intr() */ 6547 6548 6549 static uint32_t 6550 emlxs_check_attention(emlxs_hba_t *hba) 6551 { 6552 #ifdef FMA_SUPPORT 6553 emlxs_port_t *port = &PPORT; 6554 #endif /* FMA_SUPPORT */ 6555 uint32_t ha_copy; 6556 6557 ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba)); 6558 #ifdef FMA_SUPPORT 6559 /* Access handle validation */ 6560 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 6561 #endif /* FMA_SUPPORT */ 6562 return (ha_copy); 6563 6564 } /* emlxs_check_attention() */ 6565 6566 void 6567 emlxs_sli3_poll_erratt(emlxs_hba_t *hba) 6568 { 6569 uint32_t ha_copy; 6570 6571 ha_copy = emlxs_check_attention(hba); 6572 6573 /* Adapter error */ 6574 if (ha_copy & HA_ERATT) { 6575 HBASTATS.IntrEvent[6]++; 6576 emlxs_handle_ff_error(hba); 6577 } 6578 } 6579