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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * hermon_fm.c 29 * Hermon (InfiniBand) HCA Driver Fault Management Routines 30 * 31 * [Hermon FM Implementation] 32 * 33 * Hermon FM recovers the system from a HW error situation and/or isolates a 34 * HW error by calling the FMA acc handle check functions. (calling 35 * ddi_fm_acc_err_get()) If a HW error is detected when either 36 * ddi_fm_acc_err_get() is called, to determine whether or not the error is 37 * transient, the I/O operation causing the error will retry up to three times. 38 * 39 * (Basic HW error recovery) 40 * 41 * | 42 * .---->* 43 * | | 44 * | issue an I/O request via PIO 45 * | | 46 * | | 47 * | check acc handle 48 * | | 49 * | | 50 * `--< a HW error detected && retry count < 3 > 51 * | 52 * v 53 * 54 * When a HW error is detected, to provide the error information for users to 55 * isolate the faulted HW, Hermon FM issues Solaris FMA ereports as follows. 56 * 57 * * PIO transient error 58 * invalid_state => unaffected 59 * 60 * * PIO persistent error 61 * invalid_state => lost 62 * 63 * * PIO fatal error 64 * invalid_state => lost => panic 65 * 66 * * Hermon HCA firmware error 67 * invalid_state => degraded 68 * 69 * * Other Hermon HCA specific errors 70 * uncorrect => unaffected 71 * or 72 * correct => unaffected 73 * 74 * (Restrictions) 75 * 76 * The current implementation has the following restrictions. 77 * * No runtime check/protection 78 * * No detach time check/protection 79 * * No DMA check/protection 80 * 81 * See the Hermon FMA portfolio in detail. 82 */ 83 84 #include <sys/types.h> 85 #include <sys/conf.h> 86 #include <sys/ddi.h> 87 #include <sys/sunddi.h> 88 #include <sys/sysmacros.h> 89 #include <sys/list.h> 90 #include <sys/modhash.h> 91 92 #include <sys/ib/adapters/hermon/hermon.h> 93 94 /* 95 * Hermon driver has to disable its FM functionality 96 * if this "fm_capable" variable is defined or has a value 97 * in /kernel/drv/hermon.conf. 98 */ 99 static char *fm_cap = "fm-capable"; /* FM capability */ 100 101 static hermon_hca_fm_t hca_fm; /* Hermon HCA FM Structure */ 102 103 static void i_hca_fm_ereport(dev_info_t *, int, char *); 104 static void i_hca_fm_init(struct i_hca_fm *); 105 static void i_hca_fm_fini(struct i_hca_fm *); 106 static int i_hca_regs_map_setup(struct i_hca_fm *, dev_info_t *, uint_t, 107 caddr_t *, offset_t, offset_t, ddi_device_acc_attr_t *, ddi_acc_handle_t *); 108 static void i_hca_regs_map_free(struct i_hca_fm *, ddi_acc_handle_t *); 109 static int i_hca_pci_config_setup(struct i_hca_fm *, dev_info_t *, 110 ddi_acc_handle_t *); 111 static void i_hca_pci_config_teardown(struct i_hca_fm *, ddi_acc_handle_t *); 112 static int i_hca_pio_start(dev_info_t *, struct i_hca_acc_handle *, 113 hermon_test_t *); 114 static int i_hca_pio_end(dev_info_t *, struct i_hca_acc_handle *, int *, 115 hermon_test_t *); 116 static struct i_hca_acc_handle *i_hca_get_acc_handle(struct i_hca_fm *, 117 ddi_acc_handle_t); 118 119 /* forward declaration for hermon_fm_{init, fini}() */ 120 #ifdef FMA_TEST 121 static void i_hca_test_init(mod_hash_t **, mod_hash_t **); 122 static void i_hca_test_fini(mod_hash_t **, mod_hash_t **); 123 #endif /* FMA_TEST */ 124 125 /* 126 * Hermon FM Functions 127 * 128 * These functions are based on the HCA FM common interface 129 * defined below, but specific to the Hermon HCA FM capabilities. 130 */ 131 132 /* 133 * void 134 * hermon_hca_fm_init(hermon_state_t *state, hermon_hca_fm_t *hca) 135 * 136 * Overview 137 * hermon_hca_fm_init() initializes the Hermon FM resources. 138 * 139 * Argument 140 * state: pointer to Hermon state structure 141 * hca: pointer to Hermon FM structure 142 * 143 * Return value 144 * Nothing 145 * 146 * Caller's context 147 * hermon_hca_fm_init() can be called in user or kernel context only. 148 */ 149 static void 150 hermon_hca_fm_init(hermon_state_t *state, hermon_hca_fm_t *hca_fm) 151 { 152 state->hs_fm_hca_fm = hca_fm; 153 i_hca_fm_init((struct i_hca_fm *)hca_fm); 154 } 155 156 157 /* 158 * void 159 * hermon_hca_fm_fini(hermon_state_t *state) 160 * 161 * Overview 162 * hermon_hca_fm_fini() releases the Hermon FM resources. 163 * 164 * Argument 165 * state: pointer to Hermon state structure 166 * 167 * Return value 168 * Nothing 169 * 170 * Caller's context 171 * hermon_hca_fm_fini() can be called in user or kernel context only. 172 */ 173 static void 174 hermon_hca_fm_fini(hermon_state_t *state) 175 { 176 i_hca_fm_fini((struct i_hca_fm *)state->hs_fm_hca_fm); 177 state->hs_fm_hca_fm = NULL; 178 } 179 180 /* 181 * void 182 * hermon_clr_state_nolock(hermon_state_t *state, int fm_state) 183 * 184 * Overview 185 * hermon_clr_state() drops the specified state from Hermon FM state 186 * without the mutex locks. 187 * 188 * Argument 189 * state: pointer to Hermon state structure 190 * fm_state: Hermon FM state, which is composed of: 191 * HCA_NO_FM Hermom FM is not supported 192 * HCA_PIO_FM PIO is fma-protected 193 * HCA_DMA_FM DMA is fma-protected 194 * HCA_EREPORT_FM FMA ereport is available 195 * HCA_ERRCB_FM FMA error callback is supported 196 * HCA_ATTCH_FM HCA FM attach mode 197 * HCA_RUNTM_FM HCA FM runtime mode 198 * 199 * Return value 200 * Nothing 201 * 202 * Caller's context 203 * hermon_clr_state() can be called in user, kernel, interrupt context 204 * or high interrupt context. 205 */ 206 void 207 hermon_clr_state_nolock(hermon_state_t *state, int fm_state) 208 { 209 extern void membar_sync(void); 210 211 state->hs_fm_state &= ~fm_state; 212 membar_sync(); 213 } 214 215 216 /* 217 * void 218 * hermon_clr_state(hermon_state_t *state, int fm_state) 219 * 220 * Overview 221 * hermon_clr_state() drops the specified state from Hermon FM state. 222 * 223 * Argument 224 * state: pointer to Hermon state structure 225 * fm_state: Hermon FM state, which is composed of: 226 * HCA_NO_FM Hermom FM is not supported 227 * HCA_PIO_FM PIO is fma-protected 228 * HCA_DMA_FM DMA is fma-protected 229 * HCA_EREPORT_FM FMA ereport is available 230 * HCA_ERRCB_FM FMA error callback is supported 231 * HCA_ATTCH_FM HCA FM attach mode 232 * HCA_RUNTM_FM HCA FM runtime mode 233 * 234 * Return value 235 * Nothing 236 * 237 * Caller's context 238 * hermon_clr_state() can be called in user, kernel or interrupt context. 239 */ 240 static void 241 hermon_clr_state(hermon_state_t *state, int fm_state) 242 { 243 ASSERT(fm_state != HCA_NO_FM); 244 245 mutex_enter(&state->hs_fm_lock); 246 hermon_clr_state_nolock(state, fm_state); 247 mutex_exit(&state->hs_fm_lock); 248 } 249 250 251 /* 252 * void 253 * hermon_set_state(hermon_state_t *state, int fm_state) 254 * 255 * Overview 256 * hermon_set_state() sets Hermon FM state. 257 * 258 * Argument 259 * state: pointer to Hermon state structure 260 * fm_state: Hermon FM state, which is composed of: 261 * HCA_NO_FM Hermom FM is not supported 262 * HCA_PIO_FM PIO is fma-protected 263 * HCA_DMA_FM DMA is fma-protected 264 * HCA_EREPORT_FM FMA ereport is available 265 * HCA_ERRCB_FM FMA error callback is supported 266 * HCA_ATTCH_FM HCA FM attach mode 267 * HCA_RUNTM_FM HCA FM runtime mode 268 * 269 * Return value 270 * Nothing 271 * 272 * Caller's context 273 * hermon_set_state() can be called in user, kernel or interrupt context. 274 */ 275 static void 276 hermon_set_state(hermon_state_t *state, int fm_state) 277 { 278 extern void membar_sync(void); 279 280 mutex_enter(&state->hs_fm_lock); 281 if (fm_state == HCA_NO_FM) { 282 state->hs_fm_state = HCA_NO_FM; 283 } else { 284 state->hs_fm_state |= fm_state; 285 } 286 membar_sync(); 287 mutex_exit(&state->hs_fm_lock); 288 } 289 290 291 /* 292 * int 293 * hermon_get_state(hermon_state_t *state) 294 * 295 * Overview 296 * hermon_get_state() returns the current Hermon FM state. 297 * 298 * Argument 299 * state: pointer to Hermon state structure 300 * 301 * Return value 302 * fm_state: Hermon FM state, which is composed of: 303 * HCA_NO_FM Hermom FM is not supported 304 * HCA_PIO_FM PIO is fma-protected 305 * HCA_DMA_FM DMA is fma-protected 306 * HCA_EREPORT_FM FMA ereport is available 307 * HCA_ERRCB_FM FMA error callback is supported 308 * HCA_ATTCH_FM HCA FM attach mode 309 * HCA_RUNTM_FM HCA FM runtime mode 310 * 311 * Caller's context 312 * hermon_get_state() can be called in user, kernel or interrupt context. 313 */ 314 int 315 hermon_get_state(hermon_state_t *state) 316 { 317 return (state->hs_fm_state); 318 } 319 320 321 /* 322 * void 323 * hermon_fm_init(hermon_state_t *state) 324 * 325 * Overview 326 * hermon_fm_init() is a Hermon FM initialization function which registers 327 * some FMA functions such as the ereport and the acc check capabilities 328 * for Hermon. If the "fm_disable" property in /kernel/drv/hermon.conf is 329 * defined (and/or its value is set), then the Hermon FM capabilities will 330 * drop, and only the default capabilities (the ereport and error callback 331 * capabilities) are available (and the action against HW errors is 332 * issuing an ereport then panicking the system). 333 * 334 * Argument 335 * state: pointer to Hermon state structure 336 * 337 * Return value 338 * Nothing 339 * 340 * Caller's context 341 * hermon_fm_init() can be called in user or kernel context only. 342 */ 343 void 344 hermon_fm_init(hermon_state_t *state) 345 { 346 ddi_iblock_cookie_t iblk; 347 348 /* 349 * Check the "fm_disable" property. If it's defined, 350 * use the Solaris FMA default action for Hermon. 351 */ 352 if (ddi_getprop(DDI_DEV_T_NONE, state->hs_dip, DDI_PROP_DONTPASS, 353 "fm_disable", 0) != 0) { 354 state->hs_fm_disable = 1; 355 } 356 357 /* If hs_fm_diable is set, then skip the rest */ 358 if (state->hs_fm_disable) { 359 hermon_set_state(state, HCA_NO_FM); 360 return; 361 } 362 363 /* Set the Hermon FM attach mode */ 364 hermon_set_state(state, HCA_ATTCH_FM); 365 366 /* Initialize the Solaris FMA capabilities for the Hermon FM support */ 367 state->hs_fm_capabilities = ddi_prop_get_int(DDI_DEV_T_ANY, 368 state->hs_dip, DDI_PROP_DONTPASS, fm_cap, 369 DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE); 370 371 /* 372 * The Hermon FM uses the ereport and acc check capabilites only, 373 * but both of them should be available. If either is not, turn 374 * hs_fm_disable on and behave in the same way as the "fm_diable" 375 * property is set. 376 */ 377 if (state->hs_fm_capabilities != 378 (DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE)) { 379 state->hs_fm_disable = 1; 380 hermon_set_state(state, HCA_NO_FM); 381 HERMON_ATTACH_MSG(state->hs_attach_buf, 382 "Hermon FM capability fails"); 383 return; 384 } 385 386 /* Initialize the HCA FM resources */ 387 hermon_hca_fm_init(state, &hca_fm); 388 389 /* Initialize the fm state lock */ 390 mutex_init(&state->hs_fm_lock, NULL, MUTEX_DRIVER, NULL); 391 392 /* Register the capabilities with the IO fault services */ 393 ddi_fm_init(state->hs_dip, &state->hs_fm_capabilities, &iblk); 394 395 /* Set up the pci ereport capabilities if the ereport is capable */ 396 if (DDI_FM_EREPORT_CAP(state->hs_fm_capabilities)) { 397 pci_ereport_setup(state->hs_dip); 398 } 399 400 /* Set the Hermon FM state */ 401 hermon_set_state(state, HCA_PIO_FM | HCA_EREPORT_FM); 402 403 #ifdef FMA_TEST 404 i_hca_test_init(&state->hs_fm_test_hash, &state->hs_fm_id_hash); 405 #endif /* FMA_TEST */ 406 } 407 408 409 /* 410 * void 411 * hermon_fm_fini(hermon_state_t *state) 412 * 413 * Overview 414 * hermon_fm_fini() is a Hermon FM finalization function which de-registers 415 * Solaris FMA functions set to Hermon. 416 * 417 * Argument 418 * state: pointer to Hermon state structure 419 * 420 * Return value 421 * Nothing 422 * 423 * Caller's context 424 * hermon_fm_fini() can be called in user or kernel context only. 425 */ 426 void 427 hermon_fm_fini(hermon_state_t *state) 428 { 429 /* 430 * If hermon_fm_diable is set or there is no FM service provided, 431 * then skip the rest. 432 */ 433 if (state->hs_fm_disable || hermon_get_state(state) == HCA_NO_FM) { 434 return; 435 } 436 437 ASSERT(!(hermon_get_state(state) & HCA_ERRCB_FM)); 438 439 #ifdef FMA_TEST 440 i_hca_test_fini(&state->hs_fm_test_hash, &state->hs_fm_id_hash); 441 #endif /* FMA_TEST */ 442 443 /* Set the Hermon FM state to no support */ 444 hermon_set_state(state, HCA_NO_FM); 445 446 /* Release HCA FM resources */ 447 hermon_hca_fm_fini(state); 448 449 /* 450 * Release any resources allocated by pci_ereport_setup() 451 */ 452 if (DDI_FM_EREPORT_CAP(state->hs_fm_capabilities)) { 453 pci_ereport_teardown(state->hs_dip); 454 } 455 456 /* De-register the Hermon FM from the IO fault services */ 457 ddi_fm_fini(state->hs_dip); 458 } 459 460 461 /* 462 * int 463 * hermon_fm_ereport_init(hermon_state_t *state) 464 * 465 * Overview 466 * hermon_fm_ereport_init() changes the Hermon FM state to the ereport 467 * only mode during the driver attach. 468 * 469 * Argument 470 * state: pointer to Hermon state structure 471 * 472 * Return value 473 * DDI_SUCCESS 474 * DDI_FAILURE 475 * 476 * Caller's context 477 * hermon_fm_ereport_init() can be called in user or kernel context only. 478 */ 479 int 480 hermon_fm_ereport_init(hermon_state_t *state) 481 { 482 ddi_iblock_cookie_t iblk; 483 hermon_cfg_profile_t *cfgprof; 484 hermon_hw_querydevlim_t *devlim; 485 hermon_rsrc_hw_entry_info_t entry_info; 486 hermon_rsrc_pool_info_t *rsrc_pool; 487 uint64_t offset, num, max, num_prealloc; 488 ddi_device_acc_attr_t dev_attr = { 489 DDI_DEVICE_ATTR_V0, 490 DDI_STRUCTURE_LE_ACC, 491 DDI_STRICTORDER_ACC, 492 DDI_DEFAULT_ACC 493 }; 494 char *rsrc_name; 495 extern void membar_sync(void); 496 497 /* Stop the poll thread while the FM state is being changed */ 498 state->hs_fm_poll_suspend = B_TRUE; 499 membar_sync(); 500 501 /* 502 * Disable the Hermon interrupt after the interrupt capability flag 503 * is checked. 504 */ 505 if (state->hs_intrmsi_cap & DDI_INTR_FLAG_BLOCK) { 506 if (ddi_intr_block_disable 507 (&state->hs_intrmsi_hdl[0], 1) != DDI_SUCCESS) { 508 return (DDI_FAILURE); 509 } 510 } else { 511 if (ddi_intr_disable 512 (state->hs_intrmsi_hdl[0]) != DDI_SUCCESS) { 513 return (DDI_FAILURE); 514 } 515 } 516 517 /* 518 * Release any resources allocated by pci_ereport_setup() 519 */ 520 if (DDI_FM_EREPORT_CAP(state->hs_fm_capabilities)) { 521 pci_ereport_teardown(state->hs_dip); 522 } 523 524 /* De-register the Hermon FM from the IO fault services */ 525 ddi_fm_fini(state->hs_dip); 526 527 /* Re-initialize fm ereport with the ereport only */ 528 state->hs_fm_capabilities = ddi_prop_get_int(DDI_DEV_T_ANY, 529 state->hs_dip, DDI_PROP_DONTPASS, fm_cap, 530 DDI_FM_EREPORT_CAPABLE); 531 532 /* 533 * Now that the Hermon FM uses the ereport capability only, 534 * If it's not set, turn hs_fm_disable on and behave in the 535 * same way as the "fm_diable" property is set. 536 */ 537 if (state->hs_fm_capabilities != DDI_FM_EREPORT_CAPABLE) { 538 HERMON_ATTACH_MSG(state->hs_attach_buf, 539 "Hermon FM ereport fails (ereport mode)"); 540 goto error; 541 } 542 543 /* Re-register the ereport capability with the IO fault services */ 544 ddi_fm_init(state->hs_dip, &state->hs_fm_capabilities, &iblk); 545 546 /* Initialize the pci ereport capabilities if the ereport is capable */ 547 if (DDI_FM_EREPORT_CAP(state->hs_fm_capabilities)) { 548 pci_ereport_setup(state->hs_dip); 549 } 550 551 /* Setup for PCI config read/write of HCA device */ 552 if (pci_config_setup(state->hs_dip, &state->hs_reg_pcihdl) != 553 DDI_SUCCESS) { 554 HERMON_ATTACH_MSG(state->hs_attach_buf, 555 "PCI config mapping fails (ereport mode)"); 556 goto error; 557 } 558 559 /* Allocate the regular access handle for MSI-X tables */ 560 if (ddi_regs_map_setup(state->hs_dip, state->hs_msix_tbl_rnumber, 561 (caddr_t *)&state->hs_msix_tbl_addr, state->hs_msix_tbl_offset, 562 state->hs_msix_tbl_size, &dev_attr, 563 &state->hs_reg_msix_tblhdl) != DDI_SUCCESS) { 564 HERMON_ATTACH_MSG(state->hs_attach_buf, 565 "MSI-X Table mapping fails (ereport mode)"); 566 goto error; 567 } 568 569 /* Allocate the regular access handle for MSI-X PBA */ 570 if (ddi_regs_map_setup(state->hs_dip, state->hs_msix_pba_rnumber, 571 (caddr_t *)&state->hs_msix_pba_addr, state->hs_msix_pba_offset, 572 state->hs_msix_pba_size, &dev_attr, 573 &state->hs_reg_msix_pbahdl) != DDI_SUCCESS) { 574 HERMON_ATTACH_MSG(state->hs_attach_buf, 575 "MSI-X PBA mapping fails (ereport mode)"); 576 goto error; 577 } 578 579 /* Allocate the regular access handle for Hermon CMD I/O space */ 580 if (ddi_regs_map_setup(state->hs_dip, HERMON_CMD_BAR, 581 &state->hs_reg_cmd_baseaddr, 0, 0, &state->hs_reg_accattr, 582 &state->hs_reg_cmdhdl) != DDI_SUCCESS) { 583 HERMON_ATTACH_MSG(state->hs_attach_buf, 584 "CMD_BAR mapping fails (ereport mode)"); 585 goto error; 586 } 587 588 /* Reset the host command register */ 589 state->hs_cmd_regs.hcr = (hermon_hw_hcr_t *) 590 ((uintptr_t)state->hs_reg_cmd_baseaddr + HERMON_CMD_HCR_OFFSET); 591 592 /* Reset the software reset register */ 593 state->hs_cmd_regs.sw_reset = (uint32_t *) 594 ((uintptr_t)state->hs_reg_cmd_baseaddr + 595 HERMON_CMD_SW_RESET_OFFSET); 596 597 /* Reset the software reset register semaphore */ 598 state->hs_cmd_regs.sw_semaphore = (uint32_t *) 599 ((uintptr_t)state->hs_reg_cmd_baseaddr + 600 HERMON_CMD_SW_SEMAPHORE_OFFSET); 601 602 /* Calculate the clear interrupt register offset */ 603 offset = state->hs_fw.clr_intr_offs & HERMON_CMD_OFFSET_MASK; 604 605 /* Reset the clear interrupt address */ 606 state->hs_cmd_regs.clr_intr = (uint64_t *) 607 (uintptr_t)(state->hs_reg_cmd_baseaddr + offset); 608 609 /* Reset the internal error buffer address */ 610 state->hs_cmd_regs.fw_err_buf = (uint32_t *)(uintptr_t) 611 (state->hs_reg_cmd_baseaddr + state->hs_fw.error_buf_addr); 612 613 /* Check if the blue flame is enabled, and set the offset value */ 614 if (state->hs_devlim.blu_flm) { 615 offset = (uint64_t)1 << 616 (state->hs_devlim.log_max_uar_sz + 20); 617 } else { 618 offset = 0; 619 } 620 621 /* Allocate the regular access handle for Hermon UAR I/O space */ 622 if (ddi_regs_map_setup(state->hs_dip, HERMON_UAR_BAR, 623 &state->hs_reg_uar_baseaddr, 0, offset, 624 &state->hs_reg_accattr, &state->hs_reg_uarhdl) != DDI_SUCCESS) { 625 HERMON_ATTACH_MSG(state->hs_attach_buf, 626 "UAR BAR mapping fails (ereport mode)"); 627 goto error; 628 } 629 630 /* Drop the Hermon FM Attach Mode */ 631 hermon_clr_state(state, HCA_ATTCH_FM); 632 633 /* Set the Hermon FM Runtime Mode */ 634 hermon_set_state(state, HCA_RUNTM_FM); 635 636 /* Free up Hermon UAR page #1 */ 637 hermon_rsrc_free(state, &state->hs_uarkpg_rsrc); 638 639 /* Free up the UAR pool */ 640 entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_UARPG]; 641 hermon_rsrc_hw_entries_fini(state, &entry_info); 642 643 /* Re-allocate the UAR pool */ 644 cfgprof = state->hs_cfg_profile; 645 devlim = &state->hs_devlim; 646 num = ((uint64_t)1 << cfgprof->cp_log_num_uar); 647 max = num; 648 num_prealloc = max(devlim->num_rsvd_uar, 128); 649 rsrc_pool = &state->hs_rsrc_hdl[HERMON_UARPG]; 650 rsrc_pool->rsrc_type = HERMON_UARPG; 651 rsrc_pool->rsrc_loc = HERMON_IN_UAR; 652 rsrc_pool->rsrc_pool_size = (num << PAGESHIFT); 653 rsrc_pool->rsrc_shift = PAGESHIFT; 654 rsrc_pool->rsrc_quantum = (uint_t)PAGESIZE; 655 rsrc_pool->rsrc_align = PAGESIZE; 656 rsrc_pool->rsrc_state = state; 657 rsrc_pool->rsrc_start = (void *)state->hs_reg_uar_baseaddr; 658 rsrc_name = (char *)kmem_zalloc(HERMON_RSRC_NAME_MAXLEN, KM_SLEEP); 659 HERMON_RSRC_NAME(rsrc_name, HERMON_UAR_PAGE_VMEM_RUNTM); 660 entry_info.hwi_num = num; 661 entry_info.hwi_max = max; 662 entry_info.hwi_prealloc = num_prealloc; 663 entry_info.hwi_rsrcpool = rsrc_pool; 664 entry_info.hwi_rsrcname = rsrc_name; 665 if (hermon_rsrc_hw_entries_init(state, &entry_info) != DDI_SUCCESS) { 666 kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN); 667 goto error; 668 } 669 kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN); 670 671 /* Re-allocate the kernel UAR page */ 672 if (hermon_rsrc_alloc(state, HERMON_UARPG, 1, HERMON_SLEEP, 673 &state->hs_uarkpg_rsrc) != DDI_SUCCESS) { 674 goto error; 675 } 676 677 /* Setup pointer to kernel UAR page */ 678 state->hs_uar = (hermon_hw_uar_t *)state->hs_uarkpg_rsrc->hr_addr; 679 680 /* Now drop the the Hermon PIO FM */ 681 hermon_clr_state(state, HCA_PIO_FM); 682 683 /* Release the MSI-X Table access handle */ 684 if (state->hs_fm_msix_tblhdl) { 685 hermon_regs_map_free(state, &state->hs_fm_msix_tblhdl); 686 state->hs_fm_msix_tblhdl = NULL; 687 } 688 689 /* Release the MSI-X PBA access handle */ 690 if (state->hs_fm_msix_pbahdl) { 691 hermon_regs_map_free(state, &state->hs_fm_msix_pbahdl); 692 state->hs_fm_msix_pbahdl = NULL; 693 } 694 695 /* Release the pci config space access handle */ 696 if (state->hs_fm_pcihdl) { 697 hermon_regs_map_free(state, &state->hs_fm_pcihdl); 698 state->hs_fm_pcihdl = NULL; 699 } 700 701 /* Release the cmd protected access handle */ 702 if (state->hs_fm_cmdhdl) { 703 hermon_regs_map_free(state, &state->hs_fm_cmdhdl); 704 state->hs_fm_cmdhdl = NULL; 705 } 706 707 /* Release the uar fma-protected access handle */ 708 if (state->hs_fm_uarhdl) { 709 hermon_regs_map_free(state, &state->hs_fm_uarhdl); 710 state->hs_fm_uarhdl = NULL; 711 } 712 713 /* Enable the Hermon interrupt again */ 714 if (state->hs_intrmsi_cap & DDI_INTR_FLAG_BLOCK) { 715 if (ddi_intr_block_enable 716 (&state->hs_intrmsi_hdl[0], 1) != DDI_SUCCESS) { 717 return (DDI_FAILURE); 718 } 719 } else { 720 if (ddi_intr_enable 721 (state->hs_intrmsi_hdl[0]) != DDI_SUCCESS) { 722 return (DDI_FAILURE); 723 } 724 } 725 726 /* Restart the poll thread */ 727 state->hs_fm_poll_suspend = B_FALSE; 728 729 return (DDI_SUCCESS); 730 731 error: 732 /* Enable the Hermon interrupt again */ 733 if (state->hs_intrmsi_cap & DDI_INTR_FLAG_BLOCK) { 734 (void) ddi_intr_block_enable(&state->hs_intrmsi_hdl[0], 1); 735 } else { 736 (void) ddi_intr_enable(state->hs_intrmsi_hdl[0]); 737 } 738 return (DDI_FAILURE); 739 } 740 741 742 /* 743 * int 744 * hermon_regs_map_setup(hermon_state_t *state, uint_t rnumber, caddr_t *addrp, 745 * offset_t offset, offset_t len, ddi_device_acc_attr_t *accattrp, 746 * ddi_acc_handle_t *handle) 747 * 748 * Overview 749 * This is a wrapper function of i_hca_regs_map_setup() for Hermon FM so 750 * that it calls i_hca_regs_map_setup() inside after it checks the 751 * "fm_disable" configuration property. If the "fm_disable" is described 752 * in /kernel/drv/hermon.conf, the function calls ddi_regs_map_setup() 753 * directly instead. 754 * See i_hca_regs_map_setup() in detail. 755 * 756 * Argument 757 * state: pointer to Hermon state structure 758 * rnumber: index number to the register address space set 759 * addrp: platform-dependent value (same as ddi_regs_map_setup()) 760 * offset: offset into the register address space 761 * len: address space length to be mapped 762 * accattrp: pointer to device access attribute structure 763 * handle: pointer to ddi_acc_handle_t used for HCA FM 764 * 765 * Return value 766 * ddi function status value which are: 767 * DDI_SUCCESS 768 * DDI_FAILURE 769 * DDI_ME_RNUMBER_RNGE 770 * DDI_REGS_ACC_CONFLICT 771 * 772 * Caller's context 773 * hermon_regs_map_setup() can be called in user or kernel context only. 774 */ 775 int 776 hermon_regs_map_setup(hermon_state_t *state, uint_t rnumber, caddr_t *addrp, 777 offset_t offset, offset_t len, ddi_device_acc_attr_t *accattrp, 778 ddi_acc_handle_t *handle) 779 { 780 if (state->hs_fm_disable) { 781 return (ddi_regs_map_setup(state->hs_dip, rnumber, addrp, 782 offset, len, accattrp, handle)); 783 } else { 784 return (i_hca_regs_map_setup(state->hs_fm_hca_fm, state->hs_dip, 785 rnumber, addrp, offset, len, accattrp, handle)); 786 } 787 } 788 789 790 /* 791 * void 792 * hermon_regs_map_free(hermon_state_t *state, ddi_acc_handle_t *handlep) 793 * 794 * Overview 795 * This is a wrapper function of i_hca_regs_map_free() for Hermon FM so 796 * that it calls i_hca_regs_map_free() inside after it checks the 797 * "fm_disable" configuration property. If the "fm_disable" is described 798 * in /kernel/drv/hermon.conf, the function calls ddi_regs_map_fre() 799 * directly instead. See i_hca_regs_map_free() in detail. 800 * 801 * Argument 802 * state: pointer to Hermon state structure 803 * handle: pointer to ddi_acc_handle_t used for HCA FM 804 * 805 * Return value 806 * Nothing 807 * 808 * Caller's context 809 * hermon_regs_map_free() can be called in user or kernel context only. 810 * 811 * Note that the handle passed to hermon_regs_map_free() is NULL-cleared 812 * after this function is called. 813 */ 814 void 815 hermon_regs_map_free(hermon_state_t *state, ddi_acc_handle_t *handle) 816 { 817 if (state->hs_fm_disable) { 818 ddi_regs_map_free(handle); 819 *handle = NULL; 820 } else { 821 i_hca_regs_map_free(state->hs_fm_hca_fm, handle); 822 } 823 } 824 825 826 /* 827 * int 828 * hermon_pci_config_setup(hermon_state_t *state, ddi_acc_handle_t *handle) 829 * 830 * Overview 831 * This is a wrapper function of i_hca_pci_config_setup() for Hermon FM so 832 * that it calls i_hca_pci_config_setup() inside after it checks the 833 * "fm-disable" configuration property. If the "fm_disable" is described 834 * in /kernel/drv/hermon.conf, the function calls pci_config_setup() 835 * directly instead. See i_hca_pci_config_setup() in detail. 836 * 837 * Argument 838 * state: pointer to Hermon state structure 839 * handle: pointer to ddi_acc_handle_t used for HCA FM 840 * 841 * Return value 842 * ddi function status value which are: 843 * DDI_SUCCESS 844 * DDI_FAILURE 845 * 846 * Caller's context 847 * hermon_pci_config_setup() can be called in user or kernel context only. 848 */ 849 int 850 hermon_pci_config_setup(hermon_state_t *state, ddi_acc_handle_t *handle) 851 { 852 if (state->hs_fm_disable) { 853 return (pci_config_setup(state->hs_dip, handle)); 854 } else { 855 /* Check Hermon FM and Solaris FMA capability flags */ 856 ASSERT((hermon_get_state(state) & HCA_PIO_FM && 857 DDI_FM_ACC_ERR_CAP(ddi_fm_capable(state->hs_dip))) || 858 (!(hermon_get_state(state) & HCA_PIO_FM) && 859 !DDI_FM_ACC_ERR_CAP(ddi_fm_capable(state->hs_dip)))); 860 return (i_hca_pci_config_setup(state->hs_fm_hca_fm, 861 state->hs_dip, handle)); 862 } 863 } 864 865 866 /* 867 * void 868 * hermon_pci_config_teardown(hermon_state_t *state, ddi_acc_handle_t *handle) 869 * 870 * Overview 871 * This is a wrapper function of i_hca_pci_config_teardown() for Hermon 872 * FM so that it calls i_hca_pci_config_teardown() inside after it checks 873 * the "fm-disable" configuration property. If the "fm_disable" is 874 * described in /kernel/drv/hermon.conf, the function calls 875 * pci_config_teardown() directly instead. 876 * See i_hca_pci_config_teardown() in detail. 877 * 878 * Argument 879 * state: pointer to Hermon state structure 880 * handle: pointer to ddi_acc_handle_t used for HCA FM 881 * 882 * Return value 883 * Nothing 884 * 885 * Caller's context 886 * hermon_pci_config_teardown() can be called in user or kernel context 887 * only. 888 */ 889 void 890 hermon_pci_config_teardown(hermon_state_t *state, ddi_acc_handle_t *handle) 891 { 892 if (state->hs_fm_disable) { 893 pci_config_teardown(handle); 894 *handle = NULL; 895 } else { 896 i_hca_pci_config_teardown(state->hs_fm_hca_fm, handle); 897 } 898 } 899 900 901 /* 902 * boolean_t 903 * hermon_init_failure(hermon_state_t *state) 904 * 905 * Overview 906 * hermon_init_failure() tells if HW errors are detected in 907 * the Hermon driver attach. 908 * 909 * Argument 910 * state: pointer to Hermon state structure 911 * 912 * Return value 913 * B_TRUE HW errors detected during attach 914 * B_FALSE No HW errors during attach 915 * 916 * Caller's context 917 * hermon_init_failure() can be called in user, kernel, interrupt 918 * context or high interrupt context. 919 */ 920 boolean_t 921 hermon_init_failure(hermon_state_t *state) 922 { 923 ddi_acc_handle_t hdl; 924 ddi_fm_error_t derr; 925 926 if (!(hermon_get_state(state) & HCA_PIO_FM)) 927 return (B_FALSE); 928 929 hdl = hermon_get_uarhdl(state); 930 /* Get the PIO error against UAR I/O space */ 931 ddi_fm_acc_err_get(hdl, &derr, DDI_FME_VERSION); 932 if (derr.fme_status != DDI_FM_OK) { 933 return (B_TRUE); 934 } 935 936 hdl = hermon_get_cmdhdl(state); 937 /* Get the PIO error againsts CMD I/O space */ 938 ddi_fm_acc_err_get(hdl, &derr, DDI_FME_VERSION); 939 if (derr.fme_status != DDI_FM_OK) { 940 return (B_TRUE); 941 } 942 943 return (B_FALSE); 944 } 945 946 947 /* 948 * void 949 * hermon_fm_ereport(hermon_state_t *state, int type, int detail) 950 * 951 * Overview 952 * hermon_fm_ereport() is a Hermon FM ereport function used 953 * to issue a Solaris FMA ereport. See Hermon FM comments at the 954 * beginning of this file in detail. 955 * 956 * Argument 957 * state: pointer to Hermon state structure 958 * type: error type 959 * HCA_SYS_ERR FMA reporting HW error 960 * HCA_IBA_ERR HCA specific HW error 961 * detail: HW error hint implying which ereport is issued 962 * HCA_ERR_TRANSIENT HW transienet error 963 * HCA_ERR_NON_FATAL HW persistent error 964 * HCA_ERR_FATAL HW fatal error 965 * HCA_ERR_SRV_LOST IB service lost due to HW error 966 * HCA_ERR_DEGRADED Hermon driver and/or uDAPL degraded 967 * due to HW error 968 * HCA_ERR_IOCTL HW error detected in user conetxt 969 * (especially in ioctl()) 970 * 971 * Return value 972 * Nothing 973 * 974 * Caller's context 975 * hermon_fm_ereport() can be called in user, kernel, interrupt context 976 * or high interrupt context. 977 */ 978 void 979 hermon_fm_ereport(hermon_state_t *state, int type, int detail) 980 { 981 /* 982 * If hermon_fm_diable is set or there is no FM ereport service 983 * provided, then skip the rest. 984 */ 985 if (state->hs_fm_disable || 986 !(hermon_get_state(state) & HCA_EREPORT_FM)) { 987 return; 988 } 989 990 switch (type) { 991 992 case HCA_SYS_ERR: 993 switch (detail) { 994 case HCA_ERR_TRANSIENT: 995 case HCA_ERR_IOCTL: 996 ddi_fm_service_impact(state->hs_dip, 997 DDI_SERVICE_UNAFFECTED); 998 break; 999 case HCA_ERR_NON_FATAL: 1000 /* Nothing */ 1001 break; 1002 case HCA_ERR_SRV_LOST: 1003 ddi_fm_service_impact(state->hs_dip, 1004 DDI_SERVICE_LOST); 1005 break; 1006 case HCA_ERR_DEGRADED: 1007 ddi_fm_service_impact(state->hs_dip, 1008 DDI_SERVICE_DEGRADED); 1009 break; 1010 case HCA_ERR_FATAL: 1011 ddi_fm_service_impact(state->hs_dip, 1012 DDI_SERVICE_LOST); 1013 state->hs_fm_async_fatal = B_TRUE; 1014 break; 1015 default: 1016 cmn_err(CE_WARN, "hermon_fm_ereport: Unknown error. " 1017 "type = %d, detail = %d\n.", type, detail); 1018 } 1019 break; 1020 1021 case HCA_IBA_ERR: 1022 switch (detail) { 1023 case HCA_ERR_TRANSIENT: 1024 i_hca_fm_ereport(state->hs_dip, type, 1025 DDI_FM_DEVICE_INTERN_UNCORR); 1026 ddi_fm_service_impact(state->hs_dip, 1027 DDI_SERVICE_UNAFFECTED); 1028 break; 1029 case HCA_ERR_SRV_LOST: 1030 cmn_err(CE_WARN, "hermon_fm_ereport: not supported " 1031 "error. type = %d, detail = %d\n.", type, detail); 1032 break; 1033 case HCA_ERR_DEGRADED: 1034 i_hca_fm_ereport(state->hs_dip, type, 1035 DDI_FM_DEVICE_INTERN_UNCORR); 1036 ddi_fm_service_impact(state->hs_dip, 1037 DDI_SERVICE_DEGRADED); 1038 break; 1039 case HCA_ERR_IOCTL: 1040 case HCA_ERR_NON_FATAL: 1041 i_hca_fm_ereport(state->hs_dip, type, 1042 DDI_FM_DEVICE_INTERN_UNCORR); 1043 ddi_fm_service_impact(state->hs_dip, 1044 DDI_SERVICE_UNAFFECTED); 1045 break; 1046 case HCA_ERR_FATAL: 1047 if (hermon_get_state(state) & HCA_PIO_FM) { 1048 if (servicing_interrupt()) { 1049 atomic_inc_32(&state-> 1050 hs_fm_async_errcnt); 1051 } else { 1052 i_hca_fm_ereport(state->hs_dip, type, 1053 DDI_FM_DEVICE_INTERN_UNCORR); 1054 ddi_fm_service_impact(state->hs_dip, 1055 DDI_SERVICE_LOST); 1056 } 1057 state->hs_fm_async_fatal = B_TRUE; 1058 } else { 1059 i_hca_fm_ereport(state->hs_dip, type, 1060 DDI_FM_DEVICE_INTERN_UNCORR); 1061 ddi_fm_service_impact(state->hs_dip, 1062 DDI_SERVICE_LOST); 1063 cmn_err(CE_PANIC, 1064 "Hermon Fatal Internal Error. " 1065 "Hermon state=0x%p", (void *)state); 1066 } 1067 break; 1068 default: 1069 cmn_err(CE_WARN, "hermon_fm_ereport: Unknown error. " 1070 "type = %d, detail = %d\n.", type, detail); 1071 } 1072 break; 1073 1074 default: 1075 cmn_err(CE_WARN, "hermon_fm_ereport: Unknown type " 1076 "type = %d, detail = %d\n.", type, detail); 1077 break; 1078 } 1079 } 1080 1081 1082 /* 1083 * uchar_t 1084 * hermon_devacc_attr_version(hermon_state_t *) 1085 * 1086 * Overview 1087 * hermon_devacc_attr_version() returns the ddi device attribute 1088 * version. 1089 * 1090 * Argument 1091 * state: pointer to Hermon state structure 1092 * 1093 * Return value 1094 * dev_acc_attr_version value 1095 * DDI_DEVICE_ATTR_V0 Hermon FM disabled 1096 * DDI_DEVICE_ATTR_V1 Hermon FM enabled 1097 * 1098 * Caller's context 1099 * hermon_devacc_attr_version() can be called in user, kernel, interrupt 1100 * context or high interrupt context. 1101 */ 1102 ushort_t 1103 hermon_devacc_attr_version(hermon_state_t *state) 1104 { 1105 if (state->hs_fm_disable) { 1106 return (DDI_DEVICE_ATTR_V0); 1107 } else { 1108 return (DDI_DEVICE_ATTR_V1); 1109 } 1110 } 1111 1112 1113 /* 1114 * uchar_t 1115 * hermon_devacc_attr_access(hermon_state_t *) 1116 * 1117 * Overview 1118 * hermon_devacc_attr_access() returns devacc_attr_access error 1119 * protection types. 1120 * 1121 * Argument 1122 * state: pointer to Hermon state structure 1123 * 1124 * Return value 1125 * dev_acc_attr_access error protection type 1126 * DDI_DEFAULT_ACC Hermon FM disabled for PIO 1127 * DDI_FLAGERR_ACC Hermon FM enabled for PIO 1128 * 1129 * Caller's context 1130 * hermon_devacc_attr_access() can be called in user, kernel, interrupt 1131 * context or high interrupt context. 1132 */ 1133 uchar_t 1134 hermon_devacc_attr_access(hermon_state_t *state) 1135 { 1136 if (state->hs_fm_disable) { 1137 return (DDI_DEFAULT_ACC); 1138 } else { 1139 return (DDI_FLAGERR_ACC); 1140 } 1141 } 1142 1143 1144 /* 1145 * int 1146 * hermon_PIO_start(hermon_state_t *state, ddi_acc_handle_t handle, 1147 * hermon_test_t *tst) 1148 * 1149 * Overview 1150 * hermon_PIO_start() should be called before Hermon driver issues PIOs 1151 * against I/O space. If Hermon FM is disabled, this function returns 1152 * HCA_PIO_OK always. See i_hca_pio_start() in detail. 1153 * 1154 * Argument 1155 * state: pointer to Hermon state structure 1156 * handle: pointer to ddi_acc_handle_t used for HCA FM 1157 * tst: pointer to HCA FM function test structure. If the structure 1158 * is not used, the NULL value must be passed instead. 1159 * 1160 * Return value 1161 * error status showing whether or not this error can retry 1162 * HCA_PIO_OK No HW errors 1163 * HCA_PIO_TRANSIENT This error could be transient 1164 * HCA_PIO_PERSISTENT This error is persistent 1165 * 1166 * Caller's context 1167 * hermon_PIO_start() can be called in user, kernel or interrupt context. 1168 */ 1169 int 1170 hermon_PIO_start(hermon_state_t *state, ddi_acc_handle_t handle, 1171 hermon_test_t *tst) 1172 { 1173 if (state->hs_fm_disable) { 1174 return (HCA_PIO_OK); 1175 } else { 1176 struct i_hca_acc_handle *handlep = 1177 i_hca_get_acc_handle(state->hs_fm_hca_fm, handle); 1178 ASSERT(handlep != NULL); 1179 return (i_hca_pio_start(state->hs_dip, handlep, tst)); 1180 } 1181 } 1182 1183 1184 /* 1185 * int 1186 * hermon_PIO_end(hermon_state_t *state, ddi_acc_handle_t handle, int *cnt, 1187 * hermon_test_t *tst) 1188 * 1189 * Overview 1190 * hermon_PIO_end() should be called after Hermon driver issues PIOs 1191 * against I/O space. If Hermon FM is disabled, this function returns 1192 * HCA_PIO_OK always. See i_hca_pio_end() in detail. 1193 * 1194 * Argument 1195 * state: pointer to Hermon state structure 1196 * handle: pointer to ddi_acc_handle_t used for HCA FM 1197 * cnt: pointer to the counter variable which holds the nubmer of retry 1198 * (HCA_PIO_RETRY_CNT) when a HW error is detected. 1199 * tst: pointer to HCA FM function test structure. If the structure 1200 * is not used, the NULL value must be passed instead. 1201 * 1202 * Return value 1203 * error status showing whether or not this error can retry 1204 * HCA_PIO_OK No HW errors 1205 * HCA_PIO_TRANSIENT This error could be transient 1206 * HCA_PIO_PERSISTENT This error is persistent 1207 * 1208 * Caller's context 1209 * hermon_PIO_end() can be called in user, kernel or interrupt context. 1210 */ 1211 int 1212 hermon_PIO_end(hermon_state_t *state, ddi_acc_handle_t handle, int *cnt, 1213 hermon_test_t *tst) 1214 { 1215 if (state->hs_fm_disable) { 1216 return (HCA_PIO_OK); 1217 } else { 1218 struct i_hca_acc_handle *handlep = 1219 i_hca_get_acc_handle(state->hs_fm_hca_fm, handle); 1220 ASSERT(handlep != NULL); 1221 return (i_hca_pio_end(state->hs_dip, handlep, cnt, tst)); 1222 } 1223 } 1224 1225 1226 /* 1227 * ddi_acc_handle_t 1228 * hermon_get_cmdhdl(hermon_state_t *state) 1229 * 1230 * Overview 1231 * hermon_get_cmdhdl() returns either the fma-protected access handle or 1232 * the regular ddi-access handle depending on the Hermon FM state for 1233 * Hermon command I/O space. 1234 * 1235 * Argument 1236 * state: pointer to Hermon state structure 1237 * 1238 * Return value 1239 * the access handle for pio requests 1240 * 1241 * Caller's context 1242 * hermon_get_cmdhdl() can be called in user, kernel, interrupt context 1243 * or high interrupt context. 1244 */ 1245 ddi_acc_handle_t 1246 hermon_get_cmdhdl(hermon_state_t *state) 1247 { 1248 return (state->hs_fm_disable || hermon_get_state(state) & HCA_PIO_FM ? 1249 state->hs_fm_cmdhdl : state->hs_reg_cmdhdl); 1250 } 1251 1252 1253 /* 1254 * ddi_acc_handle_t 1255 * hermon_get_uarhdl(hermon_state_t *state) 1256 * 1257 * Overview 1258 * hermon_get_uarhdl() returns either the fma-protected access handle or 1259 * the regular ddi-access handle depending on the Hermon FM state for 1260 * Hermon UAR I/O space. 1261 * 1262 * Argument 1263 * state: pointer to Hermon state structure 1264 * 1265 * Return value 1266 * the access handle for pio requests 1267 * 1268 * Caller's context 1269 * hermon_get_uarhdl() can be called in user, kernel, interrupt context 1270 * or high interrupt context. 1271 */ 1272 ddi_acc_handle_t 1273 hermon_get_uarhdl(hermon_state_t *state) 1274 { 1275 return (state->hs_fm_disable || hermon_get_state(state) & HCA_PIO_FM ? 1276 state->hs_fm_uarhdl : state->hs_reg_uarhdl); 1277 } 1278 1279 1280 /* 1281 * ddi_acc_handle_t 1282 * hermon_rsrc_alloc_uarhdl(hermon_state_t *state) 1283 * 1284 * Overview 1285 * hermon_rsrc_alloc_uarhdl() returns either the fma-protected access 1286 * handle or the regular ddi-access handle depending on the Hermon FM 1287 * state for Hermon UAR I/O space as well as hermon_get_uarhdl(), but 1288 * this function is dedicated to the UAR resource allocator. 1289 * 1290 * Argument 1291 * state: pointer to Hermon state structure 1292 * 1293 * Return value 1294 * the access handle for pio requests 1295 * 1296 * Caller's context 1297 * hermon_rsrc_alloc_uarhdl() can be called in user, kernel, interrupt 1298 * or high interrupt context. 1299 */ 1300 ddi_acc_handle_t 1301 hermon_rsrc_alloc_uarhdl(hermon_state_t *state) 1302 { 1303 return (state->hs_fm_disable || hermon_get_state(state) & HCA_ATTCH_FM ? 1304 state->hs_fm_uarhdl : state->hs_reg_uarhdl); 1305 } 1306 1307 /* 1308 * ddi_acc_handle_t 1309 * hermon_get_pcihdl(hermon_state_t *state) 1310 * 1311 * Overview 1312 * hermon_get_pcihdl() returns either the fma-protected access 1313 * handle or the regular ddi-access handle to access the PCI config 1314 * space. Whether or not which handle is returned at the moment depends 1315 * on the Hermon FM state. 1316 * 1317 * Argument 1318 * state: pointer to Hermon state structure 1319 * 1320 * Return value 1321 * the access handle to PCI config space 1322 * 1323 * Caller's context 1324 * hermon_get_pcihdl() can be called in user, kernel, interrupt 1325 * or high interrupt context. 1326 */ 1327 ddi_acc_handle_t 1328 hermon_get_pcihdl(hermon_state_t *state) 1329 { 1330 return (state->hs_fm_disable || hermon_get_state(state) & HCA_ATTCH_FM ? 1331 state->hs_fm_pcihdl : state->hs_reg_pcihdl); 1332 } 1333 1334 1335 /* 1336 * ddi_acc_handle_t 1337 * hermon_get_msix_tblhdl(hermon_state_t *state) 1338 * 1339 * Overview 1340 * hermon_get_msix_tblhdl() returns either the fma-protected access 1341 * handle or the regular ddi-access handle to access the MSI-X tables. 1342 * Whether or not which handle is returned at the moment depends on 1343 * the Hermon FM state. 1344 * 1345 * Argument 1346 * state: pointer to Hermon state structure 1347 * 1348 * Return value 1349 * the access handle to MSI-X tables 1350 * 1351 * Caller's context 1352 * hermon_get_msix_tblhdl() can be called in user, kernel, interrupt 1353 * context or high interrupt context. 1354 */ 1355 ddi_acc_handle_t 1356 hermon_get_msix_tblhdl(hermon_state_t *state) 1357 { 1358 return (state->hs_fm_disable || hermon_get_state(state) & HCA_ATTCH_FM ? 1359 state->hs_fm_msix_tblhdl : state->hs_reg_msix_tblhdl); 1360 } 1361 1362 1363 /* 1364 * ddi_acc_handle_t 1365 * hermon_get_msix_pbahdl(hermon_state_t *state) 1366 * 1367 * Overview 1368 * hermon_get_msix_pbahdl() returns either the fma-protected access 1369 * handle or the regular ddi-access handle to access the MSI-X PBA. 1370 * Whether or not which handle is returned at the moment depends on 1371 * the Hermon FM state. 1372 * 1373 * Argument 1374 * state: pointer to Hermon state structure 1375 * 1376 * Return value 1377 * the access handle to MSI-X PBA 1378 * 1379 * Caller's context 1380 * hermon_get_msix_pbahdl() can be called in user, kernel, interrupt 1381 * context or high interrupt context. 1382 */ 1383 ddi_acc_handle_t 1384 hermon_get_msix_pbahdl(hermon_state_t *state) 1385 { 1386 return (state->hs_fm_disable || hermon_get_state(state) & HCA_ATTCH_FM ? 1387 state->hs_fm_msix_pbahdl : state->hs_reg_msix_pbahdl); 1388 } 1389 1390 1391 /* 1392 * void 1393 * hermon_inter_err_chk(void *arg) 1394 * 1395 * Overview 1396 * hermon_inter_err_chk() periodically checks the internal error buffer 1397 * to pick up a Hermon asynchronous internal error. 1398 * 1399 * Note that this internal error can be notified if the interrupt is 1400 * registered, but even so there are some cases that an interrupt against 1401 * it cannot be raised so that Hermon RPM recommeds to poll this internal 1402 * error buffer periodically instead. This function is invoked at 1403 * 10ms interval in kernel context though the function itself can be 1404 * called in interrupt context. 1405 * 1406 * Argument 1407 * arg: pointer to Hermon state structure 1408 * 1409 * Return value 1410 * Nothing 1411 * 1412 * Caller's context 1413 * hermon_inter_err_chk() can be called in user, kernel, interrupt 1414 * context or high interrupt context. 1415 * 1416 */ 1417 void 1418 hermon_inter_err_chk(void *arg) 1419 { 1420 uint32_t word; 1421 ddi_acc_handle_t cmdhdl; 1422 hermon_state_t *state = (hermon_state_t *)arg; 1423 1424 /* initialize the FMA retry loop */ 1425 hermon_pio_init(fm_loop_cnt, fm_status, fm_test); 1426 1427 #ifdef FMA_TEST 1428 if (hermon_test_num != 0) { 1429 return; 1430 } 1431 #endif 1432 if (state->hs_fm_poll_suspend) { 1433 return; 1434 } 1435 1436 /* Get the access handle for Hermon CMD I/O space */ 1437 cmdhdl = hermon_get_cmdhdl(state); 1438 1439 /* the FMA retry loop starts. */ 1440 hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt, fm_status, 1441 fm_test); 1442 1443 word = ddi_get32(cmdhdl, state->hs_cmd_regs.fw_err_buf); 1444 1445 /* the FMA retry loop ends. */ 1446 hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status, 1447 fm_test); 1448 1449 if (word != 0) { 1450 HERMON_FMANOTE(state, HERMON_FMA_INTERNAL); 1451 hermon_fm_ereport(state, HCA_IBA_ERR, HCA_ERR_FATAL); 1452 } 1453 1454 /* issue the ereport pended in the interrupt context */ 1455 if (state->hs_fm_async_errcnt > 0) { 1456 hermon_fm_ereport(state, HCA_IBA_ERR, HCA_ERR_FATAL); 1457 atomic_dec_32(&state->hs_fm_async_errcnt); 1458 } 1459 1460 return; 1461 1462 pio_error: 1463 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_FATAL); 1464 } 1465 1466 1467 /* 1468 * boolean_t 1469 * hermon_cmd_retry_ok(hermon_cmd_post_t *cmd, int status) 1470 * 1471 * Overview 1472 * In the case that a HW error is detected, if it can be isolated 1473 * enough, Hermon FM retries the operation which caused the error. 1474 * However, this retry can induce another error; since the retry is 1475 * achieved as a block basis, not a statement basis, once the state 1476 * was set inside the Hermon HW already in the previous operation, the 1477 * retry can cause for example, a CMD_BAD_SYS_STATE error, as a result. 1478 * In this case, CMD_BAD_SYS_STATE should be taken as a side effect 1479 * but a harmless result. hermon_cmd_retry_ok() checks this kind of 1480 * situation then returns if the state Hermon CMD returns is OK or not. 1481 * 1482 * Argument 1483 * cmd: pointer to hermon_cmd_post_t structure 1484 * status: Hermon CMD status 1485 * 1486 * Return value 1487 * B_TRUE this state is no problem 1488 * B_FALSE this state should be taken as an error 1489 * 1490 * Caller's context 1491 * hermon_cmd_retry_ok() can be called in user, kernel, interrupt 1492 * context or high interrupt context. 1493 * 1494 * Note that status except for HERMON_CMD_SUCCESS shouldn't be accepted 1495 * in the debug module to catch a hidden software bug, so that ASSERT() 1496 * is enabled in the case. 1497 */ 1498 boolean_t 1499 hermon_cmd_retry_ok(hermon_cmd_post_t *cmd, int status) 1500 { 1501 if (status == HERMON_CMD_SUCCESS) 1502 return (B_TRUE); 1503 1504 /* 1505 * The wrong status such as HERMON_CMD_BAD_SYS_STATE or 1506 * HERMON_CMD_BAD_RES_STATE can return as a side effect 1507 * because of the Hermon FM operation retry when a PIO 1508 * error is detected during the I/O transaction. In the 1509 * case, the driver may set the same value in Hermon 1510 * though it was set already, then Hermon returns HERMON_ 1511 * CMD_BAD_{RES,SYS}_STATE as a result, which should be 1512 * taken as OK. 1513 */ 1514 switch (cmd->cp_opcode) { 1515 case INIT_HCA: 1516 /* 1517 * HERMON_CMD_BAD_SYS_STATE can be gotten in case of 1518 * ICM not mapped or HCA already initialized. 1519 */ 1520 if (status == HERMON_CMD_BAD_SYS_STATE) 1521 return (B_TRUE); 1522 return (B_FALSE); 1523 1524 case CLOSE_HCA: 1525 /* 1526 * HERMON_CMD_BAD_SYS_STATE can be gotten in case of Firmware 1527 * area is not mapped or HCA already closed. 1528 */ 1529 if (status == HERMON_CMD_BAD_SYS_STATE) 1530 return (B_TRUE); 1531 return (B_FALSE); 1532 1533 case CLOSE_PORT: 1534 /* 1535 * HERMON_CMD_BAD_SYS_STATE can be gotten in case of HCA not 1536 * initialized or in case that IB ports are already down. 1537 */ 1538 if (status == HERMON_CMD_BAD_SYS_STATE) 1539 return (B_TRUE); 1540 return (B_FALSE); 1541 1542 case SW2HW_MPT: 1543 /* 1544 * HERMON_CMD_BAD_RES_STATE can be gotten in case of MPT 1545 * entry already in hardware ownership. 1546 */ 1547 if (status == HERMON_CMD_BAD_RES_STATE) 1548 return (B_TRUE); 1549 return (B_FALSE); 1550 1551 case HW2SW_MPT: 1552 /* 1553 * HERMON_CMD_BAD_RES_STATE can be gotten in case of MPT 1554 * entry already in software ownership. 1555 */ 1556 if (status == HERMON_CMD_BAD_RES_STATE) 1557 return (B_TRUE); 1558 return (B_FALSE); 1559 1560 case SW2HW_EQ: 1561 /* 1562 * HERMON_CMD_BAD_RES_STATE can be gotten in case of EQ 1563 * entry already in hardware ownership. 1564 */ 1565 if (status == HERMON_CMD_BAD_RES_STATE) 1566 return (B_TRUE); 1567 return (B_FALSE); 1568 1569 case HW2SW_EQ: 1570 /* 1571 * HERMON_CMD_BAD_RES_STATE can be gotten in case of EQ 1572 * entry already in software ownership. 1573 */ 1574 if (status == HERMON_CMD_BAD_RES_STATE) 1575 return (B_TRUE); 1576 return (B_FALSE); 1577 1578 case SW2HW_CQ: 1579 /* 1580 * HERMON_CMD_BAD_RES_STATE can be gotten in case of CQ 1581 * entry already in hardware ownership. 1582 */ 1583 if (status == HERMON_CMD_BAD_RES_STATE) 1584 return (B_TRUE); 1585 return (B_FALSE); 1586 1587 case HW2SW_CQ: 1588 /* 1589 * HERMON_CMD_BAD_RES_STATE can be gotten in case of CQ 1590 * entry already in software ownership. 1591 */ 1592 if (status == HERMON_CMD_BAD_RES_STATE) 1593 return (B_TRUE); 1594 return (B_FALSE); 1595 1596 case SW2HW_SRQ: 1597 /* 1598 * HERMON_CMD_BAD_RES_STATE can be gotten in case of SRQ 1599 * entry already in hardware ownership. 1600 */ 1601 if (status == HERMON_CMD_BAD_RES_STATE) 1602 return (B_TRUE); 1603 return (B_FALSE); 1604 1605 case HW2SW_SRQ: 1606 /* 1607 * HERMON_CMD_BAD_RES_STATE can be gotten in case of SRQ 1608 * entry already in software ownership. 1609 */ 1610 if (status == HERMON_CMD_BAD_RES_STATE) 1611 return (B_TRUE); 1612 return (B_FALSE); 1613 default: 1614 break; 1615 } 1616 1617 /* other cases */ 1618 return (B_FALSE); 1619 } 1620 1621 1622 #ifdef FMA_TEST 1623 1624 /* 1625 * Hermon FMA test variables 1626 */ 1627 #define FMA_TEST_HASHSZ 64 1628 int hermon_test_num; /* predefined testset */ 1629 1630 static struct i_hca_fm_test *i_hca_test_register(char *, int, int, 1631 void (*)(struct i_hca_fm_test *, ddi_fm_error_t *), 1632 void *, mod_hash_t *, mod_hash_t *, int); 1633 static void i_hca_test_free_item(mod_hash_val_t); 1634 static void i_hca_test_set_item(int, struct i_hca_fm_test *); 1635 static void hermon_trigger_pio_error(hermon_test_t *, ddi_fm_error_t *); 1636 1637 /* 1638 * Hermon FMA Function Test Interface 1639 */ 1640 1641 /* Attach Errors */ 1642 1643 #define ATTACH_TS (HCA_TEST_TRANSIENT | HCA_TEST_ATTACH | HCA_TEST_START) 1644 #define ATTACH_TE (HCA_TEST_TRANSIENT | HCA_TEST_ATTACH | HCA_TEST_END) 1645 1646 #define ATTACH_PS (HCA_TEST_PERSISTENT | HCA_TEST_ATTACH | HCA_TEST_START) 1647 #define ATTACH_PE (HCA_TEST_PERSISTENT | HCA_TEST_ATTACH | HCA_TEST_END) 1648 1649 static hermon_test_t testset[] = { 1650 /* Initial Value */ 1651 {0, 0, 0, NULL, 0, 0, NULL, NULL, NULL}, /* 0 */ 1652 1653 /* PIO Transient Errors */ 1654 {0, HCA_TEST_PIO, ATTACH_TS, NULL, /* attach/transient/start/propagate */ 1655 HCA_PIO_RETRY_CNT, 0, NULL, NULL, NULL}, /* 1 */ 1656 {0, HCA_TEST_PIO, ATTACH_TE, NULL, /* attach/transient/end/propagate */ 1657 HCA_PIO_RETRY_CNT, 0, NULL, NULL, NULL}, /* 2 */ 1658 1659 /* PIO Persistent Errors */ 1660 {0, HCA_TEST_PIO, ATTACH_PS, NULL, /* attach/persistent/start/propagate */ 1661 0, 0, NULL, NULL, NULL}, /* 3 */ 1662 {0, HCA_TEST_PIO, ATTACH_PE, NULL, /* attach/persistent/end/propagate */ 1663 0, 0, NULL, NULL, NULL}, /* 4 */ 1664 1665 }; 1666 1667 1668 /* 1669 * void 1670 * hermon_trigger_pio_error(hermon_test_t *tst, ddi_fm_error_t *derr) 1671 * 1672 * Overview 1673 * hermon_trigger_pio_error() is a PIO error injection function 1674 * to cause a pseduo PIO error. 1675 * 1676 * Argument 1677 * tst: pointer to HCA FM function test structure. If the structure 1678 * is not used, the NULL value must be passed instead. 1679 * derr: pointer to ddi_fm_error_t structure 1680 * 1681 * Return value 1682 * Nothing 1683 * 1684 * Caller's context 1685 * hermon_trigger_pio_error() can be called in user, kernel, interrupt 1686 * context or high interrupt context. 1687 */ 1688 static void 1689 hermon_trigger_pio_error(hermon_test_t *tst, ddi_fm_error_t *derr) 1690 { 1691 hermon_state_t *state = (hermon_state_t *)tst->private; 1692 derr->fme_status = DDI_FM_OK; 1693 1694 if (tst->type != HCA_TEST_PIO) { 1695 return; 1696 } 1697 1698 if ((tst->trigger & HCA_TEST_ATTACH && 1699 i_ddi_node_state(state->hs_dip) < DS_ATTACHED && 1700 hermon_get_state(state) & HCA_PIO_FM)) { 1701 if (tst->trigger & HCA_TEST_PERSISTENT) { 1702 i_hca_fm_ereport(state->hs_dip, HCA_IBA_ERR, 1703 DDI_FM_DEVICE_INVAL_STATE); 1704 derr->fme_status = DDI_FM_NONFATAL; 1705 return; 1706 } else if (tst->trigger & HCA_TEST_TRANSIENT && 1707 tst->errcnt) { 1708 i_hca_fm_ereport(state->hs_dip, HCA_IBA_ERR, 1709 DDI_FM_DEVICE_INVAL_STATE); 1710 derr->fme_status = DDI_FM_NONFATAL; 1711 tst->errcnt--; 1712 return; 1713 } 1714 } 1715 } 1716 1717 1718 /* 1719 * struct hermon_fm_test * 1720 * hermon_test_register(hermon_state_t *state, char *filename, int linenum, 1721 * int type) 1722 * 1723 * Overview 1724 * hermon_test_register() registers a Hermon FM test item for the 1725 * function test. 1726 * 1727 * Argument 1728 * state: pointer to Hermon state structure 1729 * filename: source file name where the function call is implemented 1730 * This value is usually a __FILE__ pre-defined macro. 1731 * linenum: line number where the function call is described in the 1732 * file specified above. 1733 * This value is usually a __LINE__ pre-defined macro. 1734 * type: HW error type 1735 * HCA_TEST_PIO pio error 1736 * HCA_TEST_IBA ib specific error 1737 * 1738 * Return value 1739 * pointer to Hermon FM function test structure registered. 1740 * 1741 * Caller's context 1742 * hermon_test_register() can be called in user, kernel or interrupt 1743 * context. 1744 * 1745 * Note that no test item is registered if Hermon FM is disabled. 1746 */ 1747 hermon_test_t * 1748 hermon_test_register(hermon_state_t *state, char *filename, int linenum, 1749 int type) 1750 { 1751 void (*pio_injection)(struct i_hca_fm_test *, ddi_fm_error_t *) = 1752 (void (*)(struct i_hca_fm_test *, ddi_fm_error_t *)) 1753 hermon_trigger_pio_error; 1754 1755 if (state->hs_fm_disable) 1756 return (NULL); 1757 1758 return ((hermon_test_t *)i_hca_test_register(filename, linenum, type, 1759 pio_injection, (void *)state, state->hs_fm_test_hash, 1760 state->hs_fm_id_hash, hermon_test_num)); 1761 } 1762 #endif /* FMA_TEST */ 1763 1764 1765 /* 1766 * HCA FM Common Interface 1767 * 1768 * These functions should be used for any HCA drivers, but probably 1769 * customized for their own HW design and/or FM implementation. 1770 * Customized functins should have the driver name prefix such as 1771 * hermon_xxxx() and be defined separately but whose functions should 1772 * call the common interface inside. 1773 */ 1774 1775 /* 1776 * void 1777 * i_hca_fm_init(struct i_hca_fm *hca_fm) 1778 * 1779 * Overview 1780 * i_hca_fm_init() is an initialization function which sets up the acc 1781 * handle kmem_cache if this function is called the first time. 1782 * 1783 * Argument 1784 * hca_fm: pointer to HCA FM structure 1785 * 1786 * Return value 1787 * Nothing 1788 * 1789 * Caller's context 1790 * i_hca_fm_init() can be called in user or kernel context, but cannot 1791 * be called in interrupt context. 1792 */ 1793 static void 1794 i_hca_fm_init(struct i_hca_fm *hca_fm) 1795 { 1796 1797 mutex_enter(&hca_fm->lock); 1798 1799 ++hca_fm->ref_cnt; 1800 if (hca_fm->fm_acc_cache == NULL) { 1801 hca_fm->fm_acc_cache = kmem_cache_create("hca_fm_acc_handle", 1802 sizeof (struct i_hca_acc_handle), 0, NULL, 1803 NULL, NULL, NULL, NULL, 0); 1804 } 1805 1806 mutex_exit(&hca_fm->lock); 1807 } 1808 1809 1810 /* 1811 * void 1812 * i_hca_fm_fini(struct i_hca_fm *hca_fm) 1813 * 1814 * Overview 1815 * i_hca_fm_fini() is a finalization function which frees up the acc 1816 * handle kmem_cache if this function is called the last time. 1817 * 1818 * Argument 1819 * hca_fm: pointer to HCA FM structure 1820 * 1821 * Return value 1822 * Nothing 1823 * 1824 * Caller's context 1825 * i_hca_fm_fini() can be called in user or kernel context, but cannot 1826 * be called in interrupt context. 1827 */ 1828 static void 1829 i_hca_fm_fini(struct i_hca_fm *hca_fm) 1830 { 1831 mutex_enter(&hca_fm->lock); 1832 1833 if (--hca_fm->ref_cnt == 0) { 1834 1835 if (hca_fm->fm_acc_cache) { 1836 kmem_cache_destroy(hca_fm->fm_acc_cache); 1837 hca_fm->fm_acc_cache = NULL; 1838 } 1839 } 1840 1841 mutex_exit(&hca_fm->lock); 1842 } 1843 1844 1845 /* 1846 * void 1847 * i_hca_fm_ereport(dev_info_t *dip, int type, char *detail) 1848 * 1849 * Overview 1850 * i_hca_fm_ereport() is a wrapper function of ddi_fm_ereport_post() but 1851 * generates an ena before it calls ddi_fm_ereport_post() for HCA 1852 * specific HW errors. 1853 * 1854 * Argument 1855 * dip: pointer to this device dev_info structure 1856 * type: error type 1857 * HCA_SYS_ERR FMA reporting HW error 1858 * HCA_IBA_ERR HCA specific HW error 1859 * detail: definition of leaf driver detected ereports which is one of: 1860 * DDI_FM_DEVICE_INVAL_STATE 1861 * DDI_FM_DEVICE_NO_RESPONSE 1862 * DDI_FM_DEVICE_STALL 1863 * DDI_FM_DEVICE_BADINT_LIMIT 1864 * DDI_FM_DEVICE_INTERN_CORR 1865 * DDI_FM_DEVICE_INTERN_UNCORR 1866 * 1867 * Return value 1868 * Nothing 1869 * 1870 * Caller's context 1871 * i_hca_fm_ereport() can be called in user, kernel or interrupt context. 1872 */ 1873 static void 1874 i_hca_fm_ereport(dev_info_t *dip, int type, char *detail) 1875 { 1876 uint64_t ena; 1877 char buf[FM_MAX_CLASS]; 1878 1879 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail); 1880 1881 ena = fm_ena_generate(0, FM_ENA_FMT1); 1882 if (type == HCA_IBA_ERR) { 1883 /* this is an error of its own */ 1884 ena = fm_ena_increment(ena); 1885 } 1886 1887 ddi_fm_ereport_post(dip, buf, ena, DDI_NOSLEEP, 1888 FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL); 1889 } 1890 1891 1892 /* 1893 * struct i_hca_acc_handle * 1894 * i_hca_get_acc_handle(struct i_hca_fm *hca_fm, ddi_acc_handle_t handle) 1895 * 1896 * Overview 1897 * i_hca_get_acc_handle() returns ddi_acc_handle_t used for HCA FM. 1898 * 1899 * Argument 1900 * hca_fm: pointer to HCA FM structure 1901 * handle: ddi_acc_handle_t 1902 * 1903 * Return value 1904 * handle: pointer to ddi_acc_handle_t used for HCA FM 1905 * 1906 * Caller's context 1907 * i_hca_get_acc_handle() can be called in user, kernel or interrupt 1908 * context. 1909 */ 1910 static struct i_hca_acc_handle * 1911 i_hca_get_acc_handle(struct i_hca_fm *hca_fm, ddi_acc_handle_t handle) 1912 { 1913 struct i_hca_acc_handle *hdlp; 1914 1915 /* Retrieve the HCA FM access handle */ 1916 mutex_enter(&hca_fm->lock); 1917 1918 for (hdlp = hca_fm->hdl; hdlp != NULL; hdlp = hdlp->next) { 1919 if (hdlp->save_hdl == handle) { 1920 mutex_exit(&hca_fm->lock); 1921 return (hdlp); 1922 } 1923 } 1924 1925 mutex_exit(&hca_fm->lock); 1926 return (hdlp); 1927 } 1928 1929 1930 /* 1931 * int 1932 * i_hca_regs_map_setup(struct i_hca_fm *hca_fm, dev_info_t *dip, 1933 * uint_t rnumber, caddr_t *addrp, offset_t offset, offset_t len, 1934 * ddi_device_acc_attr_t *accattrp, ddi_acc_handle_t *handle) 1935 * 1936 * Overview 1937 * i_hca_regs_map_setup() is a wrapper function of ddi_regs_map_setup(), 1938 * but allocates the HCA FM acc handle structure and initializes it. 1939 * 1940 * Argument 1941 * hca_fm: pointer to HCA FM structure 1942 * dip: pointer to this device dev_info structure 1943 * rnumber: index number to the register address space set 1944 * addrp: platform-dependent value (same as ddi_regs_map_setup()) 1945 * offset: offset into the register address space 1946 * len: address space length to be mapped 1947 * accattrp: pointer to device access attribute structure 1948 * handle: pointer to ddi_acc_handle_t used for HCA FM 1949 * 1950 * Return value 1951 * ddi function status value which are: 1952 * DDI_SUCCESS 1953 * DDI_FAILURE 1954 * DDI_ME_RNUMBER_RNGE 1955 * DDI_REGS_ACC_CONFLICT 1956 * 1957 * Caller's context 1958 * i_hca_regs_map_setup() can be called in user or kernel context only. 1959 */ 1960 static int 1961 i_hca_regs_map_setup(struct i_hca_fm *hca_fm, dev_info_t *dip, uint_t rnumber, 1962 caddr_t *addrp, offset_t offset, offset_t len, 1963 ddi_device_acc_attr_t *accattrp, ddi_acc_handle_t *handle) 1964 { 1965 int status; 1966 struct i_hca_acc_handle *handlep, *hdlp, *last; 1967 1968 /* Allocate an access handle */ 1969 if ((status = ddi_regs_map_setup(dip, rnumber, addrp, offset, 1970 len, accattrp, handle)) != DDI_SUCCESS) { 1971 return (status); 1972 } 1973 1974 /* Allocate HCA FM acc handle structure */ 1975 handlep = kmem_cache_alloc(hca_fm->fm_acc_cache, KM_SLEEP); 1976 1977 /* Initialize fields */ 1978 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*handlep)) 1979 handlep->next = NULL; 1980 handlep->save_hdl = (*handle); 1981 handlep->thread_cnt = 0; 1982 mutex_init(&handlep->lock, NULL, MUTEX_DRIVER, NULL); 1983 1984 /* Register this handle */ 1985 mutex_enter(&hca_fm->lock); 1986 for (last = hdlp = hca_fm->hdl; hdlp != NULL; hdlp = hdlp->next) { 1987 last = hdlp; 1988 } 1989 if (last == NULL) { 1990 hca_fm->hdl = handlep; 1991 } else { 1992 last->next = handlep; 1993 } 1994 mutex_exit(&hca_fm->lock); 1995 1996 return (status); 1997 } 1998 1999 2000 /* 2001 * void 2002 * i_hca_regs_map_free(struct i_hca_fm *hca_fm, ddi_acc_handle_t *handlep) 2003 * 2004 * Overview 2005 * i_hca_regs_map_setup() is a wrapper function of ddi_regs_map_free(), 2006 * and frees the HCA FM acc handle structure allocated by 2007 * i_hca_regs_map_setup(). 2008 * 2009 * Argument 2010 * hca_fm: pointer to HCA FM structure 2011 * handle: pointer to ddi_acc_handle_t used for HCA FM 2012 * 2013 * Return value 2014 * Nothing 2015 * 2016 * Caller's context 2017 * i_hca_regs_map_free() can be called in user or kernel context only. 2018 * 2019 * Note that the handle passed to i_hca_regs_map_free() is NULL-cleared 2020 * after this function is called. 2021 */ 2022 static void 2023 i_hca_regs_map_free(struct i_hca_fm *hca_fm, ddi_acc_handle_t *handle) 2024 { 2025 struct i_hca_acc_handle *handlep, *hdlp, *prev; 2026 2027 /* De-register this handle */ 2028 mutex_enter(&hca_fm->lock); 2029 for (prev = hdlp = hca_fm->hdl; hdlp != NULL; hdlp = hdlp->next) { 2030 if (hdlp->save_hdl == *handle) 2031 break; 2032 prev = hdlp; 2033 } 2034 ASSERT(prev != NULL && hdlp != NULL); 2035 if (hdlp != prev) { 2036 prev->next = hdlp->next; 2037 } else { 2038 hca_fm->hdl = hdlp->next; 2039 } 2040 handlep = hdlp; 2041 mutex_exit(&hca_fm->lock); 2042 2043 mutex_destroy(&handlep->lock); 2044 handlep->save_hdl = NULL; 2045 kmem_cache_free(hca_fm->fm_acc_cache, handlep); 2046 2047 /* Release this handle */ 2048 ddi_regs_map_free(handle); 2049 *handle = NULL; 2050 } 2051 2052 2053 /* 2054 * int 2055 * i_hca_pci_config_setup(struct i_hca_fm *hca_fm, dev_info_t *dip, 2056 * ddi_acc_handle_t *handle, boolean_t fm_protect) 2057 * 2058 * Overview 2059 * i_hca_pci_config_setup() is a wrapper function of pci_config_setup(), 2060 * but allocates the HCA FM acc handle structure and initializes it. 2061 * 2062 * Argument 2063 * hca_fm: pointer to HCA FM structure 2064 * dip: pointer to this device dev_info structure 2065 * handle: pointer to ddi_acc_handle_t used for HCA PCI config space 2066 * with FMA 2067 * fm_protect: flag to tell if an fma-protected access handle should 2068 * be used 2069 * 2070 * Return value 2071 * ddi function status value which are: 2072 * DDI_SUCCESS 2073 * DDI_FAILURE 2074 * 2075 * Caller's context 2076 * i_hca_pci_config_setup() can be called in user or kernel context only. 2077 */ 2078 static int 2079 i_hca_pci_config_setup(struct i_hca_fm *hca_fm, dev_info_t *dip, 2080 ddi_acc_handle_t *handle) 2081 { 2082 int status; 2083 struct i_hca_acc_handle *handlep, *hdlp, *last; 2084 2085 /* Allocate an access handle */ 2086 if ((status = pci_config_setup(dip, handle)) != DDI_SUCCESS) { 2087 return (status); 2088 } 2089 2090 /* Allocate HCA FM acc handle structure */ 2091 handlep = kmem_cache_alloc(hca_fm->fm_acc_cache, KM_SLEEP); 2092 2093 /* Initialize fields */ 2094 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*handlep)) 2095 handlep->next = NULL; 2096 handlep->save_hdl = (*handle); 2097 handlep->thread_cnt = 0; 2098 mutex_init(&handlep->lock, NULL, MUTEX_DRIVER, NULL); 2099 2100 /* Register this handle */ 2101 mutex_enter(&hca_fm->lock); 2102 for (last = hdlp = hca_fm->hdl; hdlp != NULL; hdlp = hdlp->next) { 2103 last = hdlp; 2104 } 2105 if (last == NULL) { 2106 hca_fm->hdl = handlep; 2107 } else { 2108 last->next = handlep; 2109 } 2110 mutex_exit(&hca_fm->lock); 2111 2112 return (status); 2113 } 2114 2115 2116 /* 2117 * void 2118 * i_hca_pci_config_teardown(struct i_hca_fm *hca_fm, 2119 * ddi_acc_handle_t *handlep) 2120 * 2121 * Overview 2122 * i_hca_pci_config_teardown() is a wrapper function of 2123 * pci_config_teardown(), and frees the HCA FM acc handle structure 2124 * allocated by i_hca_pci_config_setup(). 2125 * 2126 * Argument 2127 * hca_fm: pointer to HCA FM structure 2128 * handle: pointer to ddi_acc_handle_t used for HCA FM 2129 * 2130 * Return value 2131 * Nothing 2132 * 2133 * Caller's context 2134 * i_hca_pci_config_teardown() can be called in user or kernel context 2135 * only. 2136 * 2137 * Note that the handle passed to i_hca_pci_config_teardown() is NULL-cleared 2138 * after this function is called. 2139 */ 2140 static void 2141 i_hca_pci_config_teardown(struct i_hca_fm *hca_fm, ddi_acc_handle_t *handle) 2142 { 2143 struct i_hca_acc_handle *handlep, *hdlp, *prev; 2144 2145 /* De-register this handle */ 2146 mutex_enter(&hca_fm->lock); 2147 for (prev = hdlp = hca_fm->hdl; hdlp != NULL; hdlp = hdlp->next) { 2148 if (hdlp->save_hdl == *handle) 2149 break; 2150 prev = hdlp; 2151 } 2152 ASSERT(prev != NULL && hdlp != NULL); 2153 if (hdlp != prev) { 2154 prev->next = hdlp->next; 2155 } else { 2156 hca_fm->hdl = hdlp->next; 2157 } 2158 handlep = hdlp; 2159 mutex_exit(&hca_fm->lock); 2160 2161 mutex_destroy(&handlep->lock); 2162 handlep->save_hdl = NULL; 2163 kmem_cache_free(hca_fm->fm_acc_cache, handlep); 2164 2165 /* Release this handle */ 2166 pci_config_teardown(handle); 2167 *handle = NULL; 2168 } 2169 2170 2171 /* 2172 * int 2173 * i_hca_pio_start(dev_info_t *dip, struct i_acc_handle *handle, 2174 * struct i_hca_fm_test *tst) 2175 * 2176 * Overview 2177 * i_hca_pio_start() is one of a pair of HCA FM fuctions for PIO, which 2178 * should be called before HCA drivers issue PIOs against I/O space. 2179 * See HCA FM comments at the beginning of this file in detail. 2180 * 2181 * Argument 2182 * dip: pointer to this device dev_info structure 2183 * handle: pointer to ddi_acc_handle_t used for HCA FM 2184 * tst: pointer to HCA FM function test structure. If the structure 2185 * is not used, the NULL value must be passed instead. 2186 * 2187 * Return value 2188 * error status showing whether or not this error can retry 2189 * HCA_PIO_OK No HW errors 2190 * HCA_PIO_TRANSIENT This error could be transient 2191 * HCA_PIO_PERSISTENT This error is persistent 2192 * 2193 * Caller's context 2194 * i_hca_pio_start() can be called in user, kernel or interrupt context. 2195 */ 2196 /* ARGSUSED */ 2197 static int 2198 i_hca_pio_start(dev_info_t *dip, struct i_hca_acc_handle *hdlp, 2199 struct i_hca_fm_test *tst) 2200 { 2201 ddi_fm_error_t derr; 2202 2203 /* Count up the number of threads issuing this PIO */ 2204 mutex_enter(&hdlp->lock); 2205 hdlp->thread_cnt++; 2206 mutex_exit(&hdlp->lock); 2207 2208 /* Get the PIO error via FMA */ 2209 ddi_fm_acc_err_get(fm_acc_hdl(hdlp), &derr, DDI_FME_VERSION); 2210 2211 #ifdef FMA_TEST 2212 /* Trigger PIO errors */ 2213 if (tst != NULL && tst->trigger & HCA_TEST_START) { 2214 (*tst->pio_injection)(tst, &derr); 2215 } 2216 #endif /* FMA_TEST */ 2217 2218 switch (derr.fme_status) { 2219 case DDI_FM_OK: 2220 /* Not have to clear the fma error log */ 2221 return (HCA_PIO_OK); 2222 2223 case DDI_FM_NONFATAL: 2224 /* Now clear this error */ 2225 ddi_fm_acc_err_clear(fm_acc_hdl(hdlp), DDI_FME_VERSION); 2226 2227 /* Log this error and notify it as a persistent error */ 2228 ddi_fm_service_impact(dip, DDI_SERVICE_LOST); 2229 return (HCA_PIO_PERSISTENT); 2230 2231 /* In theory, this shouldn't happen */ 2232 case DDI_FM_FATAL: 2233 case DDI_FM_UNKNOWN: 2234 default: 2235 cmn_err(CE_WARN, "Unknown HCA HW error status (%d)", 2236 derr.fme_status); 2237 /* Return this as a persistent error */ 2238 return (HCA_PIO_PERSISTENT); 2239 } 2240 } 2241 2242 2243 /* 2244 * int 2245 * i_hca_pio_end(dev_info_t *dip, ddi_acc_handle_t handle, int *cnt, 2246 * struct i_hca_fm_test *tst) 2247 * 2248 * Overview 2249 * i_hca_pio_end() is the other of a pair of HCA FM fuctions for PIO, 2250 * which should be called after HCA drivers issue PIOs against I/O space. 2251 * See HCA FM comments at the beginning of this file in detail. 2252 * 2253 * Argument 2254 * dip: pointer to this device dev_info structure 2255 * handle: pointer to ddi_acc_handle_t used for HCA FM 2256 * cnt: pointer to the counter variable which holds the nubmer of retry 2257 * when a HW error is detected. 2258 * tst: pointer to HCA FM function test structure. If the structure 2259 * is not used, the NULL value must be passed instead. 2260 * 2261 * Return value 2262 * error status showing whether or not this error can retry 2263 * HCA_PIO_OK No HW errors 2264 * HCA_PIO_TRANSIENT This error could be transient 2265 * HCA_PIO_PERSISTENT This error is persistent 2266 * 2267 * Caller's context 2268 * i_hca_pio_end() can be called in user, kernel or interrupt context. 2269 */ 2270 /* ARGSUSED */ 2271 static int 2272 i_hca_pio_end(dev_info_t *dip, struct i_hca_acc_handle *hdlp, int *cnt, 2273 struct i_hca_fm_test *tst) 2274 { 2275 ddi_fm_error_t derr; 2276 2277 /* Get the PIO error via FMA */ 2278 ddi_fm_acc_err_get(fm_acc_hdl(hdlp), &derr, DDI_FME_VERSION); 2279 2280 #ifdef FMA_TEST 2281 /* Trigger PIO errors */ 2282 if (tst != NULL && tst->trigger & HCA_TEST_END) { 2283 (*tst->pio_injection)(tst, &derr); 2284 } 2285 #endif /* FMA_TEST */ 2286 2287 /* Evaluate the PIO error */ 2288 switch (derr.fme_status) { 2289 case DDI_FM_OK: 2290 /* Count down the number of threads issuing this PIO */ 2291 mutex_enter(&hdlp->lock); 2292 hdlp->thread_cnt--; 2293 mutex_exit(&hdlp->lock); 2294 2295 /* Not have to clear the fma error log */ 2296 return (HCA_PIO_OK); 2297 2298 case DDI_FM_NONFATAL: 2299 /* Now clear this error */ 2300 ddi_fm_acc_err_clear(fm_acc_hdl(hdlp), DDI_FME_VERSION); 2301 2302 /* 2303 * Check if this error comes from another thread running 2304 * with the same handle almost at the same time. 2305 */ 2306 mutex_enter(&hdlp->lock); 2307 if (hdlp->thread_cnt > 1) { 2308 /* Count down the number of threads */ 2309 hdlp->thread_cnt--; 2310 mutex_exit(&hdlp->lock); 2311 2312 /* Return this as a persistent error */ 2313 return (HCA_PIO_PERSISTENT); 2314 } 2315 mutex_exit(&hdlp->lock); 2316 2317 /* Now determine if this error is persistent or not */ 2318 if (--(*cnt) >= 0) { 2319 return (HCA_PIO_TRANSIENT); 2320 } else { 2321 /* Count down the number of threads */ 2322 mutex_enter(&hdlp->lock); 2323 hdlp->thread_cnt--; 2324 mutex_exit(&hdlp->lock); 2325 return (HCA_PIO_PERSISTENT); 2326 } 2327 2328 /* In theory, this shouldn't happen */ 2329 case DDI_FM_FATAL: 2330 case DDI_FM_UNKNOWN: 2331 default: 2332 cmn_err(CE_WARN, "Unknown HCA HW error status (%d)", 2333 derr.fme_status); 2334 /* Return this as a persistent error */ 2335 return (HCA_PIO_PERSISTENT); 2336 } 2337 } 2338 2339 2340 /* 2341 * HCA FM Test Interface 2342 * 2343 * These functions should be used for any HCA drivers, but probably 2344 * customized for their own HW design and/or FM implementation. 2345 * Customized functins should have the driver name prefix such as 2346 * hermon_xxxx() and be defined separately but whose function should 2347 * call the common interface inside. 2348 */ 2349 2350 #ifdef FMA_TEST 2351 static int test_num; /* serial number */ 2352 static kmutex_t i_hca_test_lock; /* lock for serial numer */ 2353 2354 /* 2355 * void 2356 * i_hca_test_init(mod_hash_t **strHashp, mod_hash_t **idHashp) 2357 * 2358 * Overview 2359 * i_hca_test_init() creates two hash tables, one of which is for string, 2360 * and the other of which is for ID, then saves pointers to arguments 2361 * passed. This function uses the mod_hash utilities to manage the 2362 * hash tables. About the mod_hash, see common/os/modhash.c. 2363 * 2364 * Argument 2365 * strHashp: pointer to String hash table pointer 2366 * idHashp: pointer to ID hash table pointer 2367 * 2368 * Return value 2369 * Nothing 2370 * 2371 * Caller's context 2372 * i_hca_test_init() can be called in user or kernel context only. 2373 */ 2374 static void 2375 i_hca_test_init(mod_hash_t **strHashp, mod_hash_t **idHashp) 2376 { 2377 *idHashp = mod_hash_create_idhash("HCA_FMA_id_hash", 2378 FMA_TEST_HASHSZ, mod_hash_null_valdtor); 2379 2380 *strHashp = mod_hash_create_strhash("HCA_FMA_test_hash", 2381 FMA_TEST_HASHSZ, i_hca_test_free_item); 2382 } 2383 2384 2385 /* 2386 * void 2387 * i_hca_test_fini(mod_hash_t **strHashp, mod_hash_t **idHashp) 2388 * 2389 * Overview 2390 * i_hca_test_fini() releases two hash tables used for HCA FM test. 2391 * 2392 * Argument 2393 * strHashp: pointer to String hash table pointer 2394 * idHashp: pointer to ID hash table pointer 2395 * 2396 * Return value 2397 * Nothing 2398 * 2399 * Caller's context 2400 * i_hca_test_fini() can be called in user, kernel or interrupt context. 2401 * 2402 */ 2403 static void 2404 i_hca_test_fini(mod_hash_t **strHashp, mod_hash_t **idHashp) 2405 { 2406 mod_hash_destroy_hash(*strHashp); 2407 *strHashp = NULL; 2408 2409 mod_hash_destroy_hash(*idHashp); 2410 *idHashp = NULL; 2411 } 2412 2413 2414 /* 2415 * struct i_hca_fm_test * 2416 * i_hca_test_register(char *filename, int linenum, int type, 2417 * void (*pio_injection)(struct i_hca_fm_test *, ddi_fm_error_t *), 2418 * void *private, mod_hash_t *strHash, mod_hash_t *idHash, int preTestNum) 2419 * 2420 * Overview 2421 * i_hca_test_register() registers an HCA FM test item against HCA FM 2422 * function callings specified with the file name and the line number 2423 * (passed as the arguments). 2424 * 2425 * Argument 2426 * filename: source file name where the function call is implemented 2427 * This value is usually a __FILE__ pre-defined macro. 2428 * linenum: line number where the function call is described in the 2429 * file specified above. 2430 * This value is usually a __LINE__ pre-defined macro. 2431 * type: HW error type 2432 * HCA_TEST_PIO pio error 2433 * HCA_TEST_IBA ib specific error 2434 * pio_injection: pio error injection callback function invoked when the 2435 * function specified above (with the file name and the 2436 * line number) is executed. If the function is not a PIO, 2437 * request, this parameter should be NULL. 2438 * private: the argument passed to either of injection functions when 2439 * they're invoked. 2440 * strHashp: pointer to String hash table 2441 * idHashp: pointer to ID hash table 2442 * preTestNum: the index of the pre-defined testset for this test item. 2443 * 2444 * Return value 2445 * pointer to HCA FM function test structure registered. 2446 * 2447 * Caller's context 2448 * i_hca_test_register() can be called in user, kernel or interrupt 2449 * context. 2450 * 2451 */ 2452 static struct i_hca_fm_test * 2453 i_hca_test_register(char *filename, int linenum, int type, 2454 void (*pio_injection)(struct i_hca_fm_test *, ddi_fm_error_t *), 2455 void *private, mod_hash_t *strHash, mod_hash_t *idHash, int preTestNum) 2456 { 2457 struct i_hca_fm_test *t_item; 2458 char key_buf[255], *hash_key; 2459 int status; 2460 2461 (void) sprintf(key_buf, "%s:%d", filename, linenum); 2462 hash_key = kmem_zalloc(strlen(key_buf) + 1, KM_NOSLEEP); 2463 2464 if (hash_key == NULL) 2465 cmn_err(CE_PANIC, "No memory for HCA FMA Test."); 2466 2467 bcopy(key_buf, hash_key, strlen(key_buf)); 2468 2469 status = mod_hash_find(strHash, (mod_hash_key_t)hash_key, 2470 (mod_hash_val_t *)&t_item); 2471 2472 switch (status) { 2473 case MH_ERR_NOTFOUND: 2474 t_item = (struct i_hca_fm_test *) 2475 kmem_alloc(sizeof (struct i_hca_fm_test), KM_NOSLEEP); 2476 if (t_item == NULL) 2477 cmn_err(CE_PANIC, "No memory for HCA FMA Test."); 2478 2479 /* Set the error number */ 2480 mutex_enter(&i_hca_test_lock); 2481 t_item->num = test_num++; 2482 mutex_exit(&i_hca_test_lock); 2483 2484 /* Set type and other static information */ 2485 t_item->type = type; 2486 t_item->line_num = linenum; 2487 t_item->file_name = filename; 2488 t_item->hash_key = hash_key; 2489 t_item->private = private; 2490 t_item->pio_injection = pio_injection; 2491 2492 /* Set the pre-defined hermon test item */ 2493 i_hca_test_set_item(preTestNum, (struct i_hca_fm_test *)t_item); 2494 2495 status = mod_hash_insert(strHash, (mod_hash_key_t) 2496 hash_key, (mod_hash_val_t)t_item); 2497 ASSERT(status == 0); 2498 2499 status = mod_hash_insert(idHash, (mod_hash_key_t) 2500 (uintptr_t)t_item->num, (mod_hash_val_t)t_item); 2501 ASSERT(status == 0); 2502 break; 2503 2504 case MH_ERR_NOMEM: 2505 cmn_err(CE_PANIC, "No memory for HCA FMA Test."); 2506 break; 2507 2508 case MH_ERR_DUPLICATE: 2509 cmn_err(CE_PANIC, "HCA FMA Test Internal Error."); 2510 break; 2511 default: 2512 /* OK, this is already registered. */ 2513 kmem_free(hash_key, strlen(key_buf) + 1); 2514 break; 2515 } 2516 return (t_item); 2517 } 2518 2519 2520 /* 2521 * void 2522 * i_hca_test_set_item(int num, struct i_hca_fm_test *t_item) 2523 * 2524 * Overview 2525 * i_hca_test_set_item() is a private function used in 2526 * i_hca_test_register() above. This function sets the testset specified 2527 * (with the index number) to HCA FM function test structure. 2528 * 2529 * Argument 2530 * num: index to test set (testset structure array) 2531 * t_item: pointer to HCA fM function test structure 2532 * 2533 * Return value 2534 * Nothing 2535 * 2536 * Caller's context 2537 * i_hca_test_set_item() can be called in user, kernel, interrupt 2538 * context or hight interrupt context. 2539 * 2540 */ 2541 static void 2542 i_hca_test_set_item(int num, struct i_hca_fm_test *t_item) 2543 { 2544 if (num < 0 || num >= sizeof (testset) / sizeof (hermon_test_t) || 2545 testset[num].type != t_item->type) { 2546 t_item->trigger = testset[0].trigger; 2547 t_item->errcnt = testset[0].errcnt; 2548 return; 2549 } 2550 2551 /* Set the testsuite */ 2552 t_item->trigger = testset[num].trigger; 2553 t_item->errcnt = testset[num].errcnt; 2554 } 2555 2556 2557 /* 2558 * void 2559 * i_hca_test_free_item(mod_hash_val_t val) 2560 * 2561 * Overview 2562 * i_hca_test_free_item() is a private function used to free HCA FM 2563 * function test structure when i_hca_test_fini() is called. This function 2564 * is registered as a destructor when the hash table is created in 2565 * i_hca_test_init(). 2566 * 2567 * Argument 2568 * val: pointer to the value stored in hash table (pointer to HCA FM 2569 * function test structure) 2570 * 2571 * Return value 2572 * Nothing 2573 * 2574 * Caller's context 2575 * i_hca_test_free_item() can be called in user, kernel or interrupt 2576 * context. 2577 * 2578 */ 2579 static void 2580 i_hca_test_free_item(mod_hash_val_t val) 2581 { 2582 struct i_hca_fm_test *t_item = (struct i_hca_fm_test *)val; 2583 kmem_free(t_item, sizeof (struct i_hca_fm_test)); 2584 } 2585 #endif /* FMA_TEST */ 2586