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.
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.
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]
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Hermon (InfiniBand) HCA Driver Fault Management Routines
30 * [Hermon FM Implementation]
32 * Hermon FM recovers the system from a HW error situation and/or isolates a
33 * HW error by calling the FMA acc handle check functions. (calling
34 * ddi_fm_acc_err_get()) If a HW error is detected when either
35 * ddi_fm_acc_err_get() is called, to determine whether or not the error is
36 * transient, the I/O operation causing the error will retry up to three times.
38 * (Basic HW error recovery)
43 * | issue an I/O request via PIO
49 * `--< a HW error detected && retry count < 3 >
53 * When a HW error is detected, to provide the error information for users to
54 * isolate the faulted HW, Hermon FM issues Solaris FMA ereports as follows.
56 * * PIO transient error
57 * invalid_state => unaffected
59 * * PIO persistent error
60 * invalid_state => lost
63 * invalid_state => lost => panic
65 * * Hermon HCA firmware error
66 * invalid_state => degraded
68 * * Other Hermon HCA specific errors
69 * uncorrect => unaffected
71 * correct => unaffected
75 * The current implementation has the following restrictions.
76 * * No runtime check/protection
77 * * No detach time check/protection
78 * * No DMA check/protection
80 * See the Hermon FMA portfolio in detail.
83 #include <sys/types.h>
86 #include <sys/sunddi.h>
87 #include <sys/sysmacros.h>
89 #include <sys/modhash.h>
91 #include <sys/ib/adapters/hermon/hermon.h>
94 * Hermon driver has to disable its FM functionality
95 * if this "fm_capable" variable is defined or has a value
96 * in /kernel/drv/hermon.conf.
98 static char *fm_cap
= "fm-capable"; /* FM capability */
100 static hermon_hca_fm_t hca_fm
; /* Hermon HCA FM Structure */
102 static void i_hca_fm_ereport(dev_info_t
*, int, char *);
103 static void i_hca_fm_init(struct i_hca_fm
*);
104 static void i_hca_fm_fini(struct i_hca_fm
*);
105 static int i_hca_regs_map_setup(struct i_hca_fm
*, dev_info_t
*, uint_t
,
106 caddr_t
*, offset_t
, offset_t
, ddi_device_acc_attr_t
*, ddi_acc_handle_t
*);
107 static void i_hca_regs_map_free(struct i_hca_fm
*, ddi_acc_handle_t
*);
108 static int i_hca_pci_config_setup(struct i_hca_fm
*, dev_info_t
*,
110 static void i_hca_pci_config_teardown(struct i_hca_fm
*, ddi_acc_handle_t
*);
111 static int i_hca_pio_start(dev_info_t
*, struct i_hca_acc_handle
*,
113 static int i_hca_pio_end(dev_info_t
*, struct i_hca_acc_handle
*, int *,
115 static struct i_hca_acc_handle
*i_hca_get_acc_handle(struct i_hca_fm
*,
118 /* forward declaration for hermon_fm_{init, fini}() */
120 static void i_hca_test_init(mod_hash_t
**, mod_hash_t
**);
121 static void i_hca_test_fini(mod_hash_t
**, mod_hash_t
**);
122 #endif /* FMA_TEST */
125 * Hermon FM Functions
127 * These functions are based on the HCA FM common interface
128 * defined below, but specific to the Hermon HCA FM capabilities.
133 * hermon_hca_fm_init(hermon_state_t *state, hermon_hca_fm_t *hca)
136 * hermon_hca_fm_init() initializes the Hermon FM resources.
139 * state: pointer to Hermon state structure
140 * hca: pointer to Hermon FM structure
146 * hermon_hca_fm_init() can be called in user or kernel context only.
149 hermon_hca_fm_init(hermon_state_t
*state
, hermon_hca_fm_t
*hca_fm
)
151 state
->hs_fm_hca_fm
= hca_fm
;
152 i_hca_fm_init((struct i_hca_fm
*)hca_fm
);
158 * hermon_hca_fm_fini(hermon_state_t *state)
161 * hermon_hca_fm_fini() releases the Hermon FM resources.
164 * state: pointer to Hermon state structure
170 * hermon_hca_fm_fini() can be called in user or kernel context only.
173 hermon_hca_fm_fini(hermon_state_t
*state
)
175 i_hca_fm_fini((struct i_hca_fm
*)state
->hs_fm_hca_fm
);
176 state
->hs_fm_hca_fm
= NULL
;
181 * hermon_clr_state_nolock(hermon_state_t *state, int fm_state)
184 * hermon_clr_state() drops the specified state from Hermon FM state
185 * without the mutex locks.
188 * state: pointer to Hermon state structure
189 * fm_state: Hermon FM state, which is composed of:
190 * HCA_NO_FM Hermom FM is not supported
191 * HCA_PIO_FM PIO is fma-protected
192 * HCA_DMA_FM DMA is fma-protected
193 * HCA_EREPORT_FM FMA ereport is available
194 * HCA_ERRCB_FM FMA error callback is supported
195 * HCA_ATTCH_FM HCA FM attach mode
196 * HCA_RUNTM_FM HCA FM runtime mode
202 * hermon_clr_state() can be called in user, kernel, interrupt context
203 * or high interrupt context.
206 hermon_clr_state_nolock(hermon_state_t
*state
, int fm_state
)
208 extern void membar_sync(void);
210 state
->hs_fm_state
&= ~fm_state
;
217 * hermon_clr_state(hermon_state_t *state, int fm_state)
220 * hermon_clr_state() drops the specified state from Hermon FM state.
223 * state: pointer to Hermon state structure
224 * fm_state: Hermon FM state, which is composed of:
225 * HCA_NO_FM Hermom FM is not supported
226 * HCA_PIO_FM PIO is fma-protected
227 * HCA_DMA_FM DMA is fma-protected
228 * HCA_EREPORT_FM FMA ereport is available
229 * HCA_ERRCB_FM FMA error callback is supported
230 * HCA_ATTCH_FM HCA FM attach mode
231 * HCA_RUNTM_FM HCA FM runtime mode
237 * hermon_clr_state() can be called in user, kernel or interrupt context.
240 hermon_clr_state(hermon_state_t
*state
, int fm_state
)
242 ASSERT(fm_state
!= HCA_NO_FM
);
244 mutex_enter(&state
->hs_fm_lock
);
245 hermon_clr_state_nolock(state
, fm_state
);
246 mutex_exit(&state
->hs_fm_lock
);
252 * hermon_set_state(hermon_state_t *state, int fm_state)
255 * hermon_set_state() sets Hermon FM state.
258 * state: pointer to Hermon state structure
259 * fm_state: Hermon FM state, which is composed of:
260 * HCA_NO_FM Hermom FM is not supported
261 * HCA_PIO_FM PIO is fma-protected
262 * HCA_DMA_FM DMA is fma-protected
263 * HCA_EREPORT_FM FMA ereport is available
264 * HCA_ERRCB_FM FMA error callback is supported
265 * HCA_ATTCH_FM HCA FM attach mode
266 * HCA_RUNTM_FM HCA FM runtime mode
272 * hermon_set_state() can be called in user, kernel or interrupt context.
275 hermon_set_state(hermon_state_t
*state
, int fm_state
)
277 extern void membar_sync(void);
279 mutex_enter(&state
->hs_fm_lock
);
280 if (fm_state
== HCA_NO_FM
) {
281 state
->hs_fm_state
= HCA_NO_FM
;
283 state
->hs_fm_state
|= fm_state
;
286 mutex_exit(&state
->hs_fm_lock
);
292 * hermon_get_state(hermon_state_t *state)
295 * hermon_get_state() returns the current Hermon FM state.
298 * state: pointer to Hermon state structure
301 * fm_state: Hermon FM state, which is composed of:
302 * HCA_NO_FM Hermom FM is not supported
303 * HCA_PIO_FM PIO is fma-protected
304 * HCA_DMA_FM DMA is fma-protected
305 * HCA_EREPORT_FM FMA ereport is available
306 * HCA_ERRCB_FM FMA error callback is supported
307 * HCA_ATTCH_FM HCA FM attach mode
308 * HCA_RUNTM_FM HCA FM runtime mode
311 * hermon_get_state() can be called in user, kernel or interrupt context.
314 hermon_get_state(hermon_state_t
*state
)
316 return (state
->hs_fm_state
);
322 * hermon_fm_init(hermon_state_t *state)
325 * hermon_fm_init() is a Hermon FM initialization function which registers
326 * some FMA functions such as the ereport and the acc check capabilities
327 * for Hermon. If the "fm_disable" property in /kernel/drv/hermon.conf is
328 * defined (and/or its value is set), then the Hermon FM capabilities will
329 * drop, and only the default capabilities (the ereport and error callback
330 * capabilities) are available (and the action against HW errors is
331 * issuing an ereport then panicking the system).
334 * state: pointer to Hermon state structure
340 * hermon_fm_init() can be called in user or kernel context only.
343 hermon_fm_init(hermon_state_t
*state
)
345 ddi_iblock_cookie_t iblk
;
348 * Check the "fm_disable" property. If it's defined,
349 * use the Solaris FMA default action for Hermon.
351 if (ddi_getprop(DDI_DEV_T_NONE
, state
->hs_dip
, DDI_PROP_DONTPASS
,
352 "fm_disable", 0) != 0) {
353 state
->hs_fm_disable
= 1;
356 /* If hs_fm_diable is set, then skip the rest */
357 if (state
->hs_fm_disable
) {
358 hermon_set_state(state
, HCA_NO_FM
);
362 /* Set the Hermon FM attach mode */
363 hermon_set_state(state
, HCA_ATTCH_FM
);
365 /* Initialize the Solaris FMA capabilities for the Hermon FM support */
366 state
->hs_fm_capabilities
= ddi_prop_get_int(DDI_DEV_T_ANY
,
367 state
->hs_dip
, DDI_PROP_DONTPASS
, fm_cap
,
368 DDI_FM_EREPORT_CAPABLE
| DDI_FM_ACCCHK_CAPABLE
);
371 * The Hermon FM uses the ereport and acc check capabilites only,
372 * but both of them should be available. If either is not, turn
373 * hs_fm_disable on and behave in the same way as the "fm_diable"
376 if (state
->hs_fm_capabilities
!=
377 (DDI_FM_EREPORT_CAPABLE
| DDI_FM_ACCCHK_CAPABLE
)) {
378 state
->hs_fm_disable
= 1;
379 hermon_set_state(state
, HCA_NO_FM
);
380 HERMON_ATTACH_MSG(state
->hs_attach_buf
,
381 "Hermon FM capability fails");
385 /* Initialize the HCA FM resources */
386 hermon_hca_fm_init(state
, &hca_fm
);
388 /* Initialize the fm state lock */
389 mutex_init(&state
->hs_fm_lock
, NULL
, MUTEX_DRIVER
, NULL
);
391 /* Register the capabilities with the IO fault services */
392 ddi_fm_init(state
->hs_dip
, &state
->hs_fm_capabilities
, &iblk
);
394 /* Set up the pci ereport capabilities if the ereport is capable */
395 if (DDI_FM_EREPORT_CAP(state
->hs_fm_capabilities
)) {
396 pci_ereport_setup(state
->hs_dip
);
399 /* Set the Hermon FM state */
400 hermon_set_state(state
, HCA_PIO_FM
| HCA_EREPORT_FM
);
403 i_hca_test_init(&state
->hs_fm_test_hash
, &state
->hs_fm_id_hash
);
404 #endif /* FMA_TEST */
410 * hermon_fm_fini(hermon_state_t *state)
413 * hermon_fm_fini() is a Hermon FM finalization function which de-registers
414 * Solaris FMA functions set to Hermon.
417 * state: pointer to Hermon state structure
423 * hermon_fm_fini() can be called in user or kernel context only.
426 hermon_fm_fini(hermon_state_t
*state
)
429 * If hermon_fm_diable is set or there is no FM service provided,
430 * then skip the rest.
432 if (state
->hs_fm_disable
|| hermon_get_state(state
) == HCA_NO_FM
) {
436 ASSERT(!(hermon_get_state(state
) & HCA_ERRCB_FM
));
439 i_hca_test_fini(&state
->hs_fm_test_hash
, &state
->hs_fm_id_hash
);
440 #endif /* FMA_TEST */
442 /* Set the Hermon FM state to no support */
443 hermon_set_state(state
, HCA_NO_FM
);
445 /* Release HCA FM resources */
446 hermon_hca_fm_fini(state
);
449 * Release any resources allocated by pci_ereport_setup()
451 if (DDI_FM_EREPORT_CAP(state
->hs_fm_capabilities
)) {
452 pci_ereport_teardown(state
->hs_dip
);
455 /* De-register the Hermon FM from the IO fault services */
456 ddi_fm_fini(state
->hs_dip
);
462 * hermon_fm_ereport_init(hermon_state_t *state)
465 * hermon_fm_ereport_init() changes the Hermon FM state to the ereport
466 * only mode during the driver attach.
469 * state: pointer to Hermon state structure
476 * hermon_fm_ereport_init() can be called in user or kernel context only.
479 hermon_fm_ereport_init(hermon_state_t
*state
)
481 ddi_iblock_cookie_t iblk
;
482 hermon_cfg_profile_t
*cfgprof
;
483 hermon_hw_querydevlim_t
*devlim
;
484 hermon_rsrc_hw_entry_info_t entry_info
;
485 hermon_rsrc_pool_info_t
*rsrc_pool
;
486 uint64_t offset
, num
, max
, num_prealloc
;
487 ddi_device_acc_attr_t dev_attr
= {
489 DDI_STRUCTURE_LE_ACC
,
494 extern void membar_sync(void);
496 /* Stop the poll thread while the FM state is being changed */
497 state
->hs_fm_poll_suspend
= B_TRUE
;
501 * Disable the Hermon interrupt after the interrupt capability flag
504 if (state
->hs_intrmsi_cap
& DDI_INTR_FLAG_BLOCK
) {
505 if (ddi_intr_block_disable
506 (&state
->hs_intrmsi_hdl
[0], 1) != DDI_SUCCESS
) {
507 return (DDI_FAILURE
);
511 (state
->hs_intrmsi_hdl
[0]) != DDI_SUCCESS
) {
512 return (DDI_FAILURE
);
517 * Release any resources allocated by pci_ereport_setup()
519 if (DDI_FM_EREPORT_CAP(state
->hs_fm_capabilities
)) {
520 pci_ereport_teardown(state
->hs_dip
);
523 /* De-register the Hermon FM from the IO fault services */
524 ddi_fm_fini(state
->hs_dip
);
526 /* Re-initialize fm ereport with the ereport only */
527 state
->hs_fm_capabilities
= ddi_prop_get_int(DDI_DEV_T_ANY
,
528 state
->hs_dip
, DDI_PROP_DONTPASS
, fm_cap
,
529 DDI_FM_EREPORT_CAPABLE
);
532 * Now that the Hermon FM uses the ereport capability only,
533 * If it's not set, turn hs_fm_disable on and behave in the
534 * same way as the "fm_diable" property is set.
536 if (state
->hs_fm_capabilities
!= DDI_FM_EREPORT_CAPABLE
) {
537 HERMON_ATTACH_MSG(state
->hs_attach_buf
,
538 "Hermon FM ereport fails (ereport mode)");
542 /* Re-register the ereport capability with the IO fault services */
543 ddi_fm_init(state
->hs_dip
, &state
->hs_fm_capabilities
, &iblk
);
545 /* Initialize the pci ereport capabilities if the ereport is capable */
546 if (DDI_FM_EREPORT_CAP(state
->hs_fm_capabilities
)) {
547 pci_ereport_setup(state
->hs_dip
);
550 /* Setup for PCI config read/write of HCA device */
551 if (pci_config_setup(state
->hs_dip
, &state
->hs_reg_pcihdl
) !=
553 HERMON_ATTACH_MSG(state
->hs_attach_buf
,
554 "PCI config mapping fails (ereport mode)");
558 /* Allocate the regular access handle for MSI-X tables */
559 if (ddi_regs_map_setup(state
->hs_dip
, state
->hs_msix_tbl_rnumber
,
560 (caddr_t
*)&state
->hs_msix_tbl_addr
, state
->hs_msix_tbl_offset
,
561 state
->hs_msix_tbl_size
, &dev_attr
,
562 &state
->hs_reg_msix_tblhdl
) != DDI_SUCCESS
) {
563 HERMON_ATTACH_MSG(state
->hs_attach_buf
,
564 "MSI-X Table mapping fails (ereport mode)");
568 /* Allocate the regular access handle for MSI-X PBA */
569 if (ddi_regs_map_setup(state
->hs_dip
, state
->hs_msix_pba_rnumber
,
570 (caddr_t
*)&state
->hs_msix_pba_addr
, state
->hs_msix_pba_offset
,
571 state
->hs_msix_pba_size
, &dev_attr
,
572 &state
->hs_reg_msix_pbahdl
) != DDI_SUCCESS
) {
573 HERMON_ATTACH_MSG(state
->hs_attach_buf
,
574 "MSI-X PBA mapping fails (ereport mode)");
578 /* Allocate the regular access handle for Hermon CMD I/O space */
579 if (ddi_regs_map_setup(state
->hs_dip
, HERMON_CMD_BAR
,
580 &state
->hs_reg_cmd_baseaddr
, 0, 0, &state
->hs_reg_accattr
,
581 &state
->hs_reg_cmdhdl
) != DDI_SUCCESS
) {
582 HERMON_ATTACH_MSG(state
->hs_attach_buf
,
583 "CMD_BAR mapping fails (ereport mode)");
587 /* Reset the host command register */
588 state
->hs_cmd_regs
.hcr
= (hermon_hw_hcr_t
*)
589 ((uintptr_t)state
->hs_reg_cmd_baseaddr
+ HERMON_CMD_HCR_OFFSET
);
591 /* Reset the software reset register */
592 state
->hs_cmd_regs
.sw_reset
= (uint32_t *)
593 ((uintptr_t)state
->hs_reg_cmd_baseaddr
+
594 HERMON_CMD_SW_RESET_OFFSET
);
596 /* Reset the software reset register semaphore */
597 state
->hs_cmd_regs
.sw_semaphore
= (uint32_t *)
598 ((uintptr_t)state
->hs_reg_cmd_baseaddr
+
599 HERMON_CMD_SW_SEMAPHORE_OFFSET
);
601 /* Calculate the clear interrupt register offset */
602 offset
= state
->hs_fw
.clr_intr_offs
& HERMON_CMD_OFFSET_MASK
;
604 /* Reset the clear interrupt address */
605 state
->hs_cmd_regs
.clr_intr
= (uint64_t *)
606 (uintptr_t)(state
->hs_reg_cmd_baseaddr
+ offset
);
608 /* Reset the internal error buffer address */
609 state
->hs_cmd_regs
.fw_err_buf
= (uint32_t *)(uintptr_t)
610 (state
->hs_reg_cmd_baseaddr
+ state
->hs_fw
.error_buf_addr
);
612 /* Check if the blue flame is enabled, and set the offset value */
613 if (state
->hs_devlim
.blu_flm
) {
614 offset
= (uint64_t)1 <<
615 (state
->hs_devlim
.log_max_uar_sz
+ 20);
620 /* Allocate the regular access handle for Hermon UAR I/O space */
621 if (ddi_regs_map_setup(state
->hs_dip
, HERMON_UAR_BAR
,
622 &state
->hs_reg_uar_baseaddr
, 0, offset
,
623 &state
->hs_reg_accattr
, &state
->hs_reg_uarhdl
) != DDI_SUCCESS
) {
624 HERMON_ATTACH_MSG(state
->hs_attach_buf
,
625 "UAR BAR mapping fails (ereport mode)");
629 hermon_eq_reset_uar_baseaddr(state
);
631 /* Drop the Hermon FM Attach Mode */
632 hermon_clr_state(state
, HCA_ATTCH_FM
);
634 /* Set the Hermon FM Runtime Mode */
635 hermon_set_state(state
, HCA_RUNTM_FM
);
637 /* Free up Hermon UAR page #1 */
638 hermon_rsrc_free(state
, &state
->hs_uarkpg_rsrc
);
640 /* Free up the UAR pool */
641 entry_info
.hwi_rsrcpool
= &state
->hs_rsrc_hdl
[HERMON_UARPG
];
642 hermon_rsrc_hw_entries_fini(state
, &entry_info
);
644 /* Re-allocate the UAR pool */
645 cfgprof
= state
->hs_cfg_profile
;
646 devlim
= &state
->hs_devlim
;
647 num
= ((uint64_t)1 << cfgprof
->cp_log_num_uar
);
649 num_prealloc
= max(devlim
->num_rsvd_uar
, 128);
650 rsrc_pool
= &state
->hs_rsrc_hdl
[HERMON_UARPG
];
651 rsrc_pool
->rsrc_type
= HERMON_UARPG
;
652 rsrc_pool
->rsrc_loc
= HERMON_IN_UAR
;
653 rsrc_pool
->rsrc_pool_size
= (num
<< PAGESHIFT
);
654 rsrc_pool
->rsrc_shift
= PAGESHIFT
;
655 rsrc_pool
->rsrc_quantum
= (uint_t
)PAGESIZE
;
656 rsrc_pool
->rsrc_align
= PAGESIZE
;
657 rsrc_pool
->rsrc_state
= state
;
658 rsrc_pool
->rsrc_start
= (void *)state
->hs_reg_uar_baseaddr
;
659 rsrc_name
= kmem_zalloc(HERMON_RSRC_NAME_MAXLEN
, KM_SLEEP
);
660 HERMON_RSRC_NAME(rsrc_name
, HERMON_UAR_PAGE_VMEM_RUNTM
);
661 entry_info
.hwi_num
= num
;
662 entry_info
.hwi_max
= max
;
663 entry_info
.hwi_prealloc
= num_prealloc
;
664 entry_info
.hwi_rsrcpool
= rsrc_pool
;
665 entry_info
.hwi_rsrcname
= rsrc_name
;
666 if (hermon_rsrc_hw_entries_init(state
, &entry_info
) != DDI_SUCCESS
) {
667 kmem_free(rsrc_name
, HERMON_RSRC_NAME_MAXLEN
);
670 kmem_free(rsrc_name
, HERMON_RSRC_NAME_MAXLEN
);
672 /* Re-allocate the kernel UAR page */
673 if (hermon_rsrc_alloc(state
, HERMON_UARPG
, 1, HERMON_SLEEP
,
674 &state
->hs_uarkpg_rsrc
) != DDI_SUCCESS
) {
678 /* Setup pointer to kernel UAR page */
679 state
->hs_uar
= (hermon_hw_uar_t
*)state
->hs_uarkpg_rsrc
->hr_addr
;
681 /* Now drop the the Hermon PIO FM */
682 hermon_clr_state(state
, HCA_PIO_FM
);
684 /* Release the MSI-X Table access handle */
685 if (state
->hs_fm_msix_tblhdl
) {
686 hermon_regs_map_free(state
, &state
->hs_fm_msix_tblhdl
);
687 state
->hs_fm_msix_tblhdl
= NULL
;
690 /* Release the MSI-X PBA access handle */
691 if (state
->hs_fm_msix_pbahdl
) {
692 hermon_regs_map_free(state
, &state
->hs_fm_msix_pbahdl
);
693 state
->hs_fm_msix_pbahdl
= NULL
;
696 /* Release the pci config space access handle */
697 if (state
->hs_fm_pcihdl
) {
698 hermon_regs_map_free(state
, &state
->hs_fm_pcihdl
);
699 state
->hs_fm_pcihdl
= NULL
;
702 /* Release the cmd protected access handle */
703 if (state
->hs_fm_cmdhdl
) {
704 hermon_regs_map_free(state
, &state
->hs_fm_cmdhdl
);
705 state
->hs_fm_cmdhdl
= NULL
;
708 /* Release the uar fma-protected access handle */
709 if (state
->hs_fm_uarhdl
) {
710 hermon_regs_map_free(state
, &state
->hs_fm_uarhdl
);
711 state
->hs_fm_uarhdl
= NULL
;
714 /* Enable the Hermon interrupt again */
715 if (state
->hs_intrmsi_cap
& DDI_INTR_FLAG_BLOCK
) {
716 if (ddi_intr_block_enable
717 (&state
->hs_intrmsi_hdl
[0], 1) != DDI_SUCCESS
) {
718 return (DDI_FAILURE
);
722 (state
->hs_intrmsi_hdl
[0]) != DDI_SUCCESS
) {
723 return (DDI_FAILURE
);
727 /* Restart the poll thread */
728 state
->hs_fm_poll_suspend
= B_FALSE
;
730 return (DDI_SUCCESS
);
733 /* Enable the Hermon interrupt again */
734 if (state
->hs_intrmsi_cap
& DDI_INTR_FLAG_BLOCK
) {
735 (void) ddi_intr_block_enable(&state
->hs_intrmsi_hdl
[0], 1);
737 (void) ddi_intr_enable(state
->hs_intrmsi_hdl
[0]);
739 return (DDI_FAILURE
);
745 * hermon_regs_map_setup(hermon_state_t *state, uint_t rnumber, caddr_t *addrp,
746 * offset_t offset, offset_t len, ddi_device_acc_attr_t *accattrp,
747 * ddi_acc_handle_t *handle)
750 * This is a wrapper function of i_hca_regs_map_setup() for Hermon FM so
751 * that it calls i_hca_regs_map_setup() inside after it checks the
752 * "fm_disable" configuration property. If the "fm_disable" is described
753 * in /kernel/drv/hermon.conf, the function calls ddi_regs_map_setup()
755 * See i_hca_regs_map_setup() in detail.
758 * state: pointer to Hermon state structure
759 * rnumber: index number to the register address space set
760 * addrp: platform-dependent value (same as ddi_regs_map_setup())
761 * offset: offset into the register address space
762 * len: address space length to be mapped
763 * accattrp: pointer to device access attribute structure
764 * handle: pointer to ddi_acc_handle_t used for HCA FM
767 * ddi function status value which are:
770 * DDI_ME_RNUMBER_RNGE
771 * DDI_REGS_ACC_CONFLICT
774 * hermon_regs_map_setup() can be called in user or kernel context only.
777 hermon_regs_map_setup(hermon_state_t
*state
, uint_t rnumber
, caddr_t
*addrp
,
778 offset_t offset
, offset_t len
, ddi_device_acc_attr_t
*accattrp
,
779 ddi_acc_handle_t
*handle
)
781 if (state
->hs_fm_disable
) {
782 return (ddi_regs_map_setup(state
->hs_dip
, rnumber
, addrp
,
783 offset
, len
, accattrp
, handle
));
785 return (i_hca_regs_map_setup(state
->hs_fm_hca_fm
, state
->hs_dip
,
786 rnumber
, addrp
, offset
, len
, accattrp
, handle
));
793 * hermon_regs_map_free(hermon_state_t *state, ddi_acc_handle_t *handlep)
796 * This is a wrapper function of i_hca_regs_map_free() for Hermon FM so
797 * that it calls i_hca_regs_map_free() inside after it checks the
798 * "fm_disable" configuration property. If the "fm_disable" is described
799 * in /kernel/drv/hermon.conf, the function calls ddi_regs_map_fre()
800 * directly instead. See i_hca_regs_map_free() in detail.
803 * state: pointer to Hermon state structure
804 * handle: pointer to ddi_acc_handle_t used for HCA FM
810 * hermon_regs_map_free() can be called in user or kernel context only.
812 * Note that the handle passed to hermon_regs_map_free() is NULL-cleared
813 * after this function is called.
816 hermon_regs_map_free(hermon_state_t
*state
, ddi_acc_handle_t
*handle
)
818 if (state
->hs_fm_disable
) {
819 ddi_regs_map_free(handle
);
822 i_hca_regs_map_free(state
->hs_fm_hca_fm
, handle
);
829 * hermon_pci_config_setup(hermon_state_t *state, ddi_acc_handle_t *handle)
832 * This is a wrapper function of i_hca_pci_config_setup() for Hermon FM so
833 * that it calls i_hca_pci_config_setup() inside after it checks the
834 * "fm-disable" configuration property. If the "fm_disable" is described
835 * in /kernel/drv/hermon.conf, the function calls pci_config_setup()
836 * directly instead. See i_hca_pci_config_setup() in detail.
839 * state: pointer to Hermon state structure
840 * handle: pointer to ddi_acc_handle_t used for HCA FM
843 * ddi function status value which are:
848 * hermon_pci_config_setup() can be called in user or kernel context only.
851 hermon_pci_config_setup(hermon_state_t
*state
, ddi_acc_handle_t
*handle
)
853 if (state
->hs_fm_disable
) {
854 return (pci_config_setup(state
->hs_dip
, handle
));
856 /* Check Hermon FM and Solaris FMA capability flags */
857 ASSERT((hermon_get_state(state
) & HCA_PIO_FM
&&
858 DDI_FM_ACC_ERR_CAP(ddi_fm_capable(state
->hs_dip
))) ||
859 (!(hermon_get_state(state
) & HCA_PIO_FM
) &&
860 !DDI_FM_ACC_ERR_CAP(ddi_fm_capable(state
->hs_dip
))));
861 return (i_hca_pci_config_setup(state
->hs_fm_hca_fm
,
862 state
->hs_dip
, handle
));
869 * hermon_pci_config_teardown(hermon_state_t *state, ddi_acc_handle_t *handle)
872 * This is a wrapper function of i_hca_pci_config_teardown() for Hermon
873 * FM so that it calls i_hca_pci_config_teardown() inside after it checks
874 * the "fm-disable" configuration property. If the "fm_disable" is
875 * described in /kernel/drv/hermon.conf, the function calls
876 * pci_config_teardown() directly instead.
877 * See i_hca_pci_config_teardown() in detail.
880 * state: pointer to Hermon state structure
881 * handle: pointer to ddi_acc_handle_t used for HCA FM
887 * hermon_pci_config_teardown() can be called in user or kernel context
891 hermon_pci_config_teardown(hermon_state_t
*state
, ddi_acc_handle_t
*handle
)
893 if (state
->hs_fm_disable
) {
894 pci_config_teardown(handle
);
897 i_hca_pci_config_teardown(state
->hs_fm_hca_fm
, handle
);
904 * hermon_init_failure(hermon_state_t *state)
907 * hermon_init_failure() tells if HW errors are detected in
908 * the Hermon driver attach.
911 * state: pointer to Hermon state structure
914 * B_TRUE HW errors detected during attach
915 * B_FALSE No HW errors during attach
918 * hermon_init_failure() can be called in user, kernel, interrupt
919 * context or high interrupt context.
922 hermon_init_failure(hermon_state_t
*state
)
924 ddi_acc_handle_t hdl
;
927 if (!(hermon_get_state(state
) & HCA_PIO_FM
))
930 /* check if fatal errors occur during attach */
931 if (state
->hs_fm_async_fatal
)
934 hdl
= hermon_get_uarhdl(state
);
935 /* Get the PIO error against UAR I/O space */
936 ddi_fm_acc_err_get(hdl
, &derr
, DDI_FME_VERSION
);
937 if (derr
.fme_status
!= DDI_FM_OK
) {
941 hdl
= hermon_get_cmdhdl(state
);
942 /* Get the PIO error againsts CMD I/O space */
943 ddi_fm_acc_err_get(hdl
, &derr
, DDI_FME_VERSION
);
944 if (derr
.fme_status
!= DDI_FM_OK
) {
954 * hermon_fm_ereport(hermon_state_t *state, int type, int detail)
957 * hermon_fm_ereport() is a Hermon FM ereport function used
958 * to issue a Solaris FMA ereport. See Hermon FM comments at the
959 * beginning of this file in detail.
962 * state: pointer to Hermon state structure
964 * HCA_SYS_ERR FMA reporting HW error
965 * HCA_IBA_ERR HCA specific HW error
966 * detail: HW error hint implying which ereport is issued
967 * HCA_ERR_TRANSIENT HW transienet error
968 * HCA_ERR_NON_FATAL HW persistent error
969 * HCA_ERR_FATAL HW fatal error
970 * HCA_ERR_SRV_LOST IB service lost due to HW error
971 * HCA_ERR_DEGRADED Hermon driver and/or uDAPL degraded
973 * HCA_ERR_IOCTL HW error detected in user conetxt
974 * (especially in ioctl())
980 * hermon_fm_ereport() can be called in user, kernel, interrupt context
981 * or high interrupt context.
984 hermon_fm_ereport(hermon_state_t
*state
, int type
, int detail
)
987 * If hermon_fm_diable is set or there is no FM ereport service
988 * provided, then skip the rest.
990 if (state
->hs_fm_disable
||
991 !(hermon_get_state(state
) & HCA_EREPORT_FM
)) {
999 case HCA_ERR_TRANSIENT
:
1001 ddi_fm_service_impact(state
->hs_dip
,
1002 DDI_SERVICE_UNAFFECTED
);
1004 case HCA_ERR_NON_FATAL
:
1007 case HCA_ERR_SRV_LOST
:
1008 ddi_fm_service_impact(state
->hs_dip
,
1011 case HCA_ERR_DEGRADED
:
1012 switch (state
->hs_fm_degraded_reason
) {
1013 case HCA_FW_CORRUPT
:
1014 i_hca_fm_ereport(state
->hs_dip
, type
,
1015 DDI_FM_DEVICE_FW_CORRUPT
);
1017 case HCA_FW_MISMATCH
:
1018 i_hca_fm_ereport(state
->hs_dip
, type
,
1019 DDI_FM_DEVICE_FW_MISMATCH
);
1023 i_hca_fm_ereport(state
->hs_dip
, type
,
1024 DDI_FM_DEVICE_INTERN_UNCORR
);
1027 ddi_fm_service_impact(state
->hs_dip
,
1028 DDI_SERVICE_DEGRADED
);
1031 ddi_fm_service_impact(state
->hs_dip
,
1033 state
->hs_fm_async_fatal
= B_TRUE
;
1036 cmn_err(CE_WARN
, "hermon_fm_ereport: Unknown error. "
1037 "type = %d, detail = %d\n.", type
, detail
);
1043 case HCA_ERR_TRANSIENT
:
1044 i_hca_fm_ereport(state
->hs_dip
, type
,
1045 DDI_FM_DEVICE_INTERN_UNCORR
);
1046 ddi_fm_service_impact(state
->hs_dip
,
1047 DDI_SERVICE_UNAFFECTED
);
1049 case HCA_ERR_SRV_LOST
:
1050 cmn_err(CE_WARN
, "hermon_fm_ereport: not supported "
1051 "error. type = %d, detail = %d\n.", type
, detail
);
1053 case HCA_ERR_DEGRADED
:
1054 switch (state
->hs_fm_degraded_reason
) {
1055 case HCA_FW_CORRUPT
:
1056 i_hca_fm_ereport(state
->hs_dip
, type
,
1057 DDI_FM_DEVICE_FW_CORRUPT
);
1059 case HCA_FW_MISMATCH
:
1060 i_hca_fm_ereport(state
->hs_dip
, type
,
1061 DDI_FM_DEVICE_FW_MISMATCH
);
1065 i_hca_fm_ereport(state
->hs_dip
, type
,
1066 DDI_FM_DEVICE_INTERN_UNCORR
);
1069 ddi_fm_service_impact(state
->hs_dip
,
1070 DDI_SERVICE_DEGRADED
);
1073 case HCA_ERR_NON_FATAL
:
1074 i_hca_fm_ereport(state
->hs_dip
, type
,
1075 DDI_FM_DEVICE_INTERN_UNCORR
);
1076 ddi_fm_service_impact(state
->hs_dip
,
1077 DDI_SERVICE_UNAFFECTED
);
1080 if (hermon_get_state(state
) & HCA_PIO_FM
) {
1081 if (servicing_interrupt()) {
1082 atomic_inc_32(&state
->
1083 hs_fm_async_errcnt
);
1085 i_hca_fm_ereport(state
->hs_dip
, type
,
1086 DDI_FM_DEVICE_INTERN_UNCORR
);
1087 ddi_fm_service_impact(state
->hs_dip
,
1090 state
->hs_fm_async_fatal
= B_TRUE
;
1092 i_hca_fm_ereport(state
->hs_dip
, type
,
1093 DDI_FM_DEVICE_INTERN_UNCORR
);
1094 ddi_fm_service_impact(state
->hs_dip
,
1097 "Hermon Fatal Internal Error. "
1098 "Hermon state=0x%p", (void *)state
);
1102 cmn_err(CE_WARN
, "hermon_fm_ereport: Unknown error. "
1103 "type = %d, detail = %d\n.", type
, detail
);
1108 cmn_err(CE_WARN
, "hermon_fm_ereport: Unknown type "
1109 "type = %d, detail = %d\n.", type
, detail
);
1117 * hermon_devacc_attr_version(hermon_state_t *)
1120 * hermon_devacc_attr_version() returns the ddi device attribute
1124 * state: pointer to Hermon state structure
1127 * dev_acc_attr_version value
1128 * DDI_DEVICE_ATTR_V0 Hermon FM disabled
1129 * DDI_DEVICE_ATTR_V1 Hermon FM enabled
1132 * hermon_devacc_attr_version() can be called in user, kernel, interrupt
1133 * context or high interrupt context.
1136 hermon_devacc_attr_version(hermon_state_t
*state
)
1138 if (state
->hs_fm_disable
) {
1139 return (DDI_DEVICE_ATTR_V0
);
1141 return (DDI_DEVICE_ATTR_V1
);
1148 * hermon_devacc_attr_access(hermon_state_t *)
1151 * hermon_devacc_attr_access() returns devacc_attr_access error
1155 * state: pointer to Hermon state structure
1158 * dev_acc_attr_access error protection type
1159 * DDI_DEFAULT_ACC Hermon FM disabled for PIO
1160 * DDI_FLAGERR_ACC Hermon FM enabled for PIO
1163 * hermon_devacc_attr_access() can be called in user, kernel, interrupt
1164 * context or high interrupt context.
1167 hermon_devacc_attr_access(hermon_state_t
*state
)
1169 if (state
->hs_fm_disable
) {
1170 return (DDI_DEFAULT_ACC
);
1172 return (DDI_FLAGERR_ACC
);
1179 * hermon_PIO_start(hermon_state_t *state, ddi_acc_handle_t handle,
1180 * hermon_test_t *tst)
1183 * hermon_PIO_start() should be called before Hermon driver issues PIOs
1184 * against I/O space. If Hermon FM is disabled, this function returns
1185 * HCA_PIO_OK always. See i_hca_pio_start() in detail.
1188 * state: pointer to Hermon state structure
1189 * handle: pointer to ddi_acc_handle_t used for HCA FM
1190 * tst: pointer to HCA FM function test structure. If the structure
1191 * is not used, the NULL value must be passed instead.
1194 * error status showing whether or not this error can retry
1195 * HCA_PIO_OK No HW errors
1196 * HCA_PIO_TRANSIENT This error could be transient
1197 * HCA_PIO_PERSISTENT This error is persistent
1200 * hermon_PIO_start() can be called in user, kernel or interrupt context.
1203 hermon_PIO_start(hermon_state_t
*state
, ddi_acc_handle_t handle
,
1206 if (state
->hs_fm_disable
) {
1207 return (HCA_PIO_OK
);
1209 struct i_hca_acc_handle
*handlep
=
1210 i_hca_get_acc_handle(state
->hs_fm_hca_fm
, handle
);
1211 ASSERT(handlep
!= NULL
);
1212 return (i_hca_pio_start(state
->hs_dip
, handlep
, tst
));
1219 * hermon_PIO_end(hermon_state_t *state, ddi_acc_handle_t handle, int *cnt,
1220 * hermon_test_t *tst)
1223 * hermon_PIO_end() should be called after Hermon driver issues PIOs
1224 * against I/O space. If Hermon FM is disabled, this function returns
1225 * HCA_PIO_OK always. See i_hca_pio_end() in detail.
1228 * state: pointer to Hermon state structure
1229 * handle: pointer to ddi_acc_handle_t used for HCA FM
1230 * cnt: pointer to the counter variable which holds the nubmer of retry
1231 * (HCA_PIO_RETRY_CNT) when a HW error is detected.
1232 * tst: pointer to HCA FM function test structure. If the structure
1233 * is not used, the NULL value must be passed instead.
1236 * error status showing whether or not this error can retry
1237 * HCA_PIO_OK No HW errors
1238 * HCA_PIO_TRANSIENT This error could be transient
1239 * HCA_PIO_PERSISTENT This error is persistent
1242 * hermon_PIO_end() can be called in user, kernel or interrupt context.
1245 hermon_PIO_end(hermon_state_t
*state
, ddi_acc_handle_t handle
, int *cnt
,
1248 if (state
->hs_fm_disable
) {
1249 return (HCA_PIO_OK
);
1251 struct i_hca_acc_handle
*handlep
=
1252 i_hca_get_acc_handle(state
->hs_fm_hca_fm
, handle
);
1253 ASSERT(handlep
!= NULL
);
1254 return (i_hca_pio_end(state
->hs_dip
, handlep
, cnt
, tst
));
1261 * hermon_get_cmdhdl(hermon_state_t *state)
1264 * hermon_get_cmdhdl() returns either the fma-protected access handle or
1265 * the regular ddi-access handle depending on the Hermon FM state for
1266 * Hermon command I/O space.
1269 * state: pointer to Hermon state structure
1272 * the access handle for pio requests
1275 * hermon_get_cmdhdl() can be called in user, kernel, interrupt context
1276 * or high interrupt context.
1279 hermon_get_cmdhdl(hermon_state_t
*state
)
1281 return (state
->hs_fm_disable
|| hermon_get_state(state
) & HCA_PIO_FM
?
1282 state
->hs_fm_cmdhdl
: state
->hs_reg_cmdhdl
);
1288 * hermon_get_uarhdl(hermon_state_t *state)
1291 * hermon_get_uarhdl() returns either the fma-protected access handle or
1292 * the regular ddi-access handle depending on the Hermon FM state for
1293 * Hermon UAR I/O space.
1296 * state: pointer to Hermon state structure
1299 * the access handle for pio requests
1302 * hermon_get_uarhdl() can be called in user, kernel, interrupt context
1303 * or high interrupt context.
1306 hermon_get_uarhdl(hermon_state_t
*state
)
1308 return (state
->hs_fm_disable
|| hermon_get_state(state
) & HCA_PIO_FM
?
1309 state
->hs_fm_uarhdl
: state
->hs_reg_uarhdl
);
1315 * hermon_rsrc_alloc_uarhdl(hermon_state_t *state)
1318 * hermon_rsrc_alloc_uarhdl() returns either the fma-protected access
1319 * handle or the regular ddi-access handle depending on the Hermon FM
1320 * state for Hermon UAR I/O space as well as hermon_get_uarhdl(), but
1321 * this function is dedicated to the UAR resource allocator.
1324 * state: pointer to Hermon state structure
1327 * the access handle for pio requests
1330 * hermon_rsrc_alloc_uarhdl() can be called in user, kernel, interrupt
1331 * or high interrupt context.
1334 hermon_rsrc_alloc_uarhdl(hermon_state_t
*state
)
1336 return (state
->hs_fm_disable
|| hermon_get_state(state
) & HCA_ATTCH_FM
?
1337 state
->hs_fm_uarhdl
: state
->hs_reg_uarhdl
);
1342 * hermon_get_pcihdl(hermon_state_t *state)
1345 * hermon_get_pcihdl() returns either the fma-protected access
1346 * handle or the regular ddi-access handle to access the PCI config
1347 * space. Whether or not which handle is returned at the moment depends
1348 * on the Hermon FM state.
1351 * state: pointer to Hermon state structure
1354 * the access handle to PCI config space
1357 * hermon_get_pcihdl() can be called in user, kernel, interrupt
1358 * or high interrupt context.
1361 hermon_get_pcihdl(hermon_state_t
*state
)
1363 return (state
->hs_fm_disable
|| hermon_get_state(state
) & HCA_ATTCH_FM
?
1364 state
->hs_fm_pcihdl
: state
->hs_reg_pcihdl
);
1370 * hermon_get_msix_tblhdl(hermon_state_t *state)
1373 * hermon_get_msix_tblhdl() returns either the fma-protected access
1374 * handle or the regular ddi-access handle to access the MSI-X tables.
1375 * Whether or not which handle is returned at the moment depends on
1376 * the Hermon FM state.
1379 * state: pointer to Hermon state structure
1382 * the access handle to MSI-X tables
1385 * hermon_get_msix_tblhdl() can be called in user, kernel, interrupt
1386 * context or high interrupt context.
1389 hermon_get_msix_tblhdl(hermon_state_t
*state
)
1391 return (state
->hs_fm_disable
|| hermon_get_state(state
) & HCA_ATTCH_FM
?
1392 state
->hs_fm_msix_tblhdl
: state
->hs_reg_msix_tblhdl
);
1398 * hermon_get_msix_pbahdl(hermon_state_t *state)
1401 * hermon_get_msix_pbahdl() returns either the fma-protected access
1402 * handle or the regular ddi-access handle to access the MSI-X PBA.
1403 * Whether or not which handle is returned at the moment depends on
1404 * the Hermon FM state.
1407 * state: pointer to Hermon state structure
1410 * the access handle to MSI-X PBA
1413 * hermon_get_msix_pbahdl() can be called in user, kernel, interrupt
1414 * context or high interrupt context.
1417 hermon_get_msix_pbahdl(hermon_state_t
*state
)
1419 return (state
->hs_fm_disable
|| hermon_get_state(state
) & HCA_ATTCH_FM
?
1420 state
->hs_fm_msix_pbahdl
: state
->hs_reg_msix_pbahdl
);
1426 * hermon_inter_err_chk(void *arg)
1429 * hermon_inter_err_chk() periodically checks the internal error buffer
1430 * to pick up a Hermon asynchronous internal error.
1432 * Note that this internal error can be notified if the interrupt is
1433 * registered, but even so there are some cases that an interrupt against
1434 * it cannot be raised so that Hermon RPM recommeds to poll this internal
1435 * error buffer periodically instead. This function is invoked at
1436 * 10ms interval in kernel context though the function itself can be
1437 * called in interrupt context.
1440 * arg: pointer to Hermon state structure
1446 * hermon_inter_err_chk() can be called in user, kernel, interrupt
1447 * context or high interrupt context.
1451 hermon_inter_err_chk(void *arg
)
1454 ddi_acc_handle_t cmdhdl
;
1455 hermon_state_t
*state
= (hermon_state_t
*)arg
;
1457 /* initialize the FMA retry loop */
1458 hermon_pio_init(fm_loop_cnt
, fm_status
, fm_test
);
1461 if (hermon_test_num
!= 0) {
1465 if (state
->hs_fm_poll_suspend
) {
1469 /* Get the access handle for Hermon CMD I/O space */
1470 cmdhdl
= hermon_get_cmdhdl(state
);
1472 /* the FMA retry loop starts. */
1473 hermon_pio_start(state
, cmdhdl
, pio_error
, fm_loop_cnt
, fm_status
,
1476 word
= ddi_get32(cmdhdl
, state
->hs_cmd_regs
.fw_err_buf
);
1478 /* the FMA retry loop ends. */
1479 hermon_pio_end(state
, cmdhdl
, pio_error
, fm_loop_cnt
, fm_status
,
1483 HERMON_FMANOTE(state
, HERMON_FMA_INTERNAL
);
1484 /* if fm_disable is on, Hermon FM functions don't work */
1485 if (state
->hs_fm_disable
) {
1487 "Hermon Fatal Internal Error. "
1488 "Hermon state=0x%p", (void *)state
);
1490 hermon_fm_ereport(state
, HCA_IBA_ERR
, HCA_ERR_FATAL
);
1494 /* issue the ereport pended in the interrupt context */
1495 if (state
->hs_fm_async_errcnt
> 0) {
1496 hermon_fm_ereport(state
, HCA_IBA_ERR
, HCA_ERR_FATAL
);
1497 atomic_dec_32(&state
->hs_fm_async_errcnt
);
1503 hermon_fm_ereport(state
, HCA_SYS_ERR
, HCA_ERR_FATAL
);
1509 * hermon_cmd_retry_ok(hermon_cmd_post_t *cmd, int status)
1512 * In the case that a HW error is detected, if it can be isolated
1513 * enough, Hermon FM retries the operation which caused the error.
1514 * However, this retry can induce another error; since the retry is
1515 * achieved as a block basis, not a statement basis, once the state
1516 * was set inside the Hermon HW already in the previous operation, the
1517 * retry can cause for example, a CMD_BAD_SYS_STATE error, as a result.
1518 * In this case, CMD_BAD_SYS_STATE should be taken as a side effect
1519 * but a harmless result. hermon_cmd_retry_ok() checks this kind of
1520 * situation then returns if the state Hermon CMD returns is OK or not.
1523 * cmd: pointer to hermon_cmd_post_t structure
1524 * status: Hermon CMD status
1527 * B_TRUE this state is no problem
1528 * B_FALSE this state should be taken as an error
1531 * hermon_cmd_retry_ok() can be called in user, kernel, interrupt
1532 * context or high interrupt context.
1534 * Note that status except for HERMON_CMD_SUCCESS shouldn't be accepted
1535 * in the debug module to catch a hidden software bug, so that ASSERT()
1536 * is enabled in the case.
1539 hermon_cmd_retry_ok(hermon_cmd_post_t
*cmd
, int status
)
1541 if (status
== HERMON_CMD_SUCCESS
)
1545 * The wrong status such as HERMON_CMD_BAD_SYS_STATE or
1546 * HERMON_CMD_BAD_RES_STATE can return as a side effect
1547 * because of the Hermon FM operation retry when a PIO
1548 * error is detected during the I/O transaction. In the
1549 * case, the driver may set the same value in Hermon
1550 * though it was set already, then Hermon returns HERMON_
1551 * CMD_BAD_{RES,SYS}_STATE as a result, which should be
1554 switch (cmd
->cp_opcode
) {
1557 * HERMON_CMD_BAD_SYS_STATE can be gotten in case of
1558 * ICM not mapped or HCA already initialized.
1560 if (status
== HERMON_CMD_BAD_SYS_STATE
)
1566 * HERMON_CMD_BAD_SYS_STATE can be gotten in case of Firmware
1567 * area is not mapped or HCA already closed.
1569 if (status
== HERMON_CMD_BAD_SYS_STATE
)
1575 * HERMON_CMD_BAD_SYS_STATE can be gotten in case of HCA not
1576 * initialized or in case that IB ports are already down.
1578 if (status
== HERMON_CMD_BAD_SYS_STATE
)
1584 * HERMON_CMD_BAD_RES_STATE can be gotten in case of MPT
1585 * entry already in hardware ownership.
1587 if (status
== HERMON_CMD_BAD_RES_STATE
)
1593 * HERMON_CMD_BAD_RES_STATE can be gotten in case of MPT
1594 * entry already in software ownership.
1596 if (status
== HERMON_CMD_BAD_RES_STATE
)
1602 * HERMON_CMD_BAD_RES_STATE can be gotten in case of EQ
1603 * entry already in hardware ownership.
1605 if (status
== HERMON_CMD_BAD_RES_STATE
)
1611 * HERMON_CMD_BAD_RES_STATE can be gotten in case of EQ
1612 * entry already in software ownership.
1614 if (status
== HERMON_CMD_BAD_RES_STATE
)
1620 * HERMON_CMD_BAD_RES_STATE can be gotten in case of CQ
1621 * entry already in hardware ownership.
1623 if (status
== HERMON_CMD_BAD_RES_STATE
)
1629 * HERMON_CMD_BAD_RES_STATE can be gotten in case of CQ
1630 * entry already in software ownership.
1632 if (status
== HERMON_CMD_BAD_RES_STATE
)
1638 * HERMON_CMD_BAD_RES_STATE can be gotten in case of SRQ
1639 * entry already in hardware ownership.
1641 if (status
== HERMON_CMD_BAD_RES_STATE
)
1647 * HERMON_CMD_BAD_RES_STATE can be gotten in case of SRQ
1648 * entry already in software ownership.
1650 if (status
== HERMON_CMD_BAD_RES_STATE
)
1665 * Hermon FMA test variables
1667 #define FMA_TEST_HASHSZ 64
1668 int hermon_test_num
; /* predefined testset */
1670 static struct i_hca_fm_test
*i_hca_test_register(char *, int, int,
1671 void (*)(struct i_hca_fm_test
*, ddi_fm_error_t
*),
1672 void *, mod_hash_t
*, mod_hash_t
*, int);
1673 static void i_hca_test_free_item(mod_hash_val_t
);
1674 static void i_hca_test_set_item(int, struct i_hca_fm_test
*);
1675 static void hermon_trigger_pio_error(hermon_test_t
*, ddi_fm_error_t
*);
1678 * Hermon FMA Function Test Interface
1683 #define ATTACH_TS (HCA_TEST_TRANSIENT | HCA_TEST_ATTACH | HCA_TEST_START)
1684 #define ATTACH_TE (HCA_TEST_TRANSIENT | HCA_TEST_ATTACH | HCA_TEST_END)
1686 #define ATTACH_PS (HCA_TEST_PERSISTENT | HCA_TEST_ATTACH | HCA_TEST_START)
1687 #define ATTACH_PE (HCA_TEST_PERSISTENT | HCA_TEST_ATTACH | HCA_TEST_END)
1689 static hermon_test_t testset
[] = {
1691 {0, 0, 0, NULL
, 0, 0, NULL
, NULL
, NULL
}, /* 0 */
1693 /* PIO Transient Errors */
1694 {0, HCA_TEST_PIO
, ATTACH_TS
, NULL
, /* attach/transient/start/propagate */
1695 HCA_PIO_RETRY_CNT
, 0, NULL
, NULL
, NULL
}, /* 1 */
1696 {0, HCA_TEST_PIO
, ATTACH_TE
, NULL
, /* attach/transient/end/propagate */
1697 HCA_PIO_RETRY_CNT
, 0, NULL
, NULL
, NULL
}, /* 2 */
1699 /* PIO Persistent Errors */
1700 {0, HCA_TEST_PIO
, ATTACH_PS
, NULL
, /* attach/persistent/start/propagate */
1701 0, 0, NULL
, NULL
, NULL
}, /* 3 */
1702 {0, HCA_TEST_PIO
, ATTACH_PE
, NULL
, /* attach/persistent/end/propagate */
1703 0, 0, NULL
, NULL
, NULL
}, /* 4 */
1710 * hermon_trigger_pio_error(hermon_test_t *tst, ddi_fm_error_t *derr)
1713 * hermon_trigger_pio_error() is a PIO error injection function
1714 * to cause a pseduo PIO error.
1717 * tst: pointer to HCA FM function test structure. If the structure
1718 * is not used, the NULL value must be passed instead.
1719 * derr: pointer to ddi_fm_error_t structure
1725 * hermon_trigger_pio_error() can be called in user, kernel, interrupt
1726 * context or high interrupt context.
1729 hermon_trigger_pio_error(hermon_test_t
*tst
, ddi_fm_error_t
*derr
)
1731 hermon_state_t
*state
= (hermon_state_t
*)tst
->private;
1732 derr
->fme_status
= DDI_FM_OK
;
1734 if (tst
->type
!= HCA_TEST_PIO
) {
1738 if ((tst
->trigger
& HCA_TEST_ATTACH
&&
1739 i_ddi_node_state(state
->hs_dip
) < DS_ATTACHED
&&
1740 hermon_get_state(state
) & HCA_PIO_FM
)) {
1741 if (tst
->trigger
& HCA_TEST_PERSISTENT
) {
1742 i_hca_fm_ereport(state
->hs_dip
, HCA_IBA_ERR
,
1743 DDI_FM_DEVICE_INVAL_STATE
);
1744 derr
->fme_status
= DDI_FM_NONFATAL
;
1746 } else if (tst
->trigger
& HCA_TEST_TRANSIENT
&&
1748 i_hca_fm_ereport(state
->hs_dip
, HCA_IBA_ERR
,
1749 DDI_FM_DEVICE_INVAL_STATE
);
1750 derr
->fme_status
= DDI_FM_NONFATAL
;
1759 * struct hermon_fm_test *
1760 * hermon_test_register(hermon_state_t *state, char *filename, int linenum,
1764 * hermon_test_register() registers a Hermon FM test item for the
1768 * state: pointer to Hermon state structure
1769 * filename: source file name where the function call is implemented
1770 * This value is usually a __FILE__ pre-defined macro.
1771 * linenum: line number where the function call is described in the
1772 * file specified above.
1773 * This value is usually a __LINE__ pre-defined macro.
1774 * type: HW error type
1775 * HCA_TEST_PIO pio error
1776 * HCA_TEST_IBA ib specific error
1779 * pointer to Hermon FM function test structure registered.
1782 * hermon_test_register() can be called in user, kernel or interrupt
1785 * Note that no test item is registered if Hermon FM is disabled.
1788 hermon_test_register(hermon_state_t
*state
, char *filename
, int linenum
,
1791 void (*pio_injection
)(struct i_hca_fm_test
*, ddi_fm_error_t
*) =
1792 (void (*)(struct i_hca_fm_test
*, ddi_fm_error_t
*))
1793 hermon_trigger_pio_error
;
1795 if (state
->hs_fm_disable
)
1798 return ((hermon_test_t
*)i_hca_test_register(filename
, linenum
, type
,
1799 pio_injection
, (void *)state
, state
->hs_fm_test_hash
,
1800 state
->hs_fm_id_hash
, hermon_test_num
));
1802 #endif /* FMA_TEST */
1806 * HCA FM Common Interface
1808 * These functions should be used for any HCA drivers, but probably
1809 * customized for their own HW design and/or FM implementation.
1810 * Customized functins should have the driver name prefix such as
1811 * hermon_xxxx() and be defined separately but whose functions should
1812 * call the common interface inside.
1817 * i_hca_fm_init(struct i_hca_fm *hca_fm)
1820 * i_hca_fm_init() is an initialization function which sets up the acc
1821 * handle kmem_cache if this function is called the first time.
1824 * hca_fm: pointer to HCA FM structure
1830 * i_hca_fm_init() can be called in user or kernel context, but cannot
1831 * be called in interrupt context.
1834 i_hca_fm_init(struct i_hca_fm
*hca_fm
)
1837 mutex_enter(&hca_fm
->lock
);
1840 if (hca_fm
->fm_acc_cache
== NULL
) {
1841 hca_fm
->fm_acc_cache
= kmem_cache_create("hca_fm_acc_handle",
1842 sizeof (struct i_hca_acc_handle
), 0, NULL
,
1843 NULL
, NULL
, NULL
, NULL
, 0);
1846 mutex_exit(&hca_fm
->lock
);
1852 * i_hca_fm_fini(struct i_hca_fm *hca_fm)
1855 * i_hca_fm_fini() is a finalization function which frees up the acc
1856 * handle kmem_cache if this function is called the last time.
1859 * hca_fm: pointer to HCA FM structure
1865 * i_hca_fm_fini() can be called in user or kernel context, but cannot
1866 * be called in interrupt context.
1869 i_hca_fm_fini(struct i_hca_fm
*hca_fm
)
1871 mutex_enter(&hca_fm
->lock
);
1873 if (--hca_fm
->ref_cnt
== 0) {
1875 if (hca_fm
->fm_acc_cache
) {
1876 kmem_cache_destroy(hca_fm
->fm_acc_cache
);
1877 hca_fm
->fm_acc_cache
= NULL
;
1881 mutex_exit(&hca_fm
->lock
);
1887 * i_hca_fm_ereport(dev_info_t *dip, int type, char *detail)
1890 * i_hca_fm_ereport() is a wrapper function of ddi_fm_ereport_post() but
1891 * generates an ena before it calls ddi_fm_ereport_post() for HCA
1892 * specific HW errors.
1895 * dip: pointer to this device dev_info structure
1897 * HCA_SYS_ERR FMA reporting HW error
1898 * HCA_IBA_ERR HCA specific HW error
1899 * detail: definition of leaf driver detected ereports which is one of:
1900 * DDI_FM_DEVICE_INVAL_STATE
1901 * DDI_FM_DEVICE_NO_RESPONSE
1902 * DDI_FM_DEVICE_STALL
1903 * DDI_FM_DEVICE_BADINT_LIMIT
1904 * DDI_FM_DEVICE_INTERN_CORR
1905 * DDI_FM_DEVICE_INTERN_UNCORR
1911 * i_hca_fm_ereport() can be called in user, kernel or interrupt context.
1914 i_hca_fm_ereport(dev_info_t
*dip
, int type
, char *detail
)
1917 char buf
[FM_MAX_CLASS
];
1919 (void) snprintf(buf
, FM_MAX_CLASS
, "%s.%s", DDI_FM_DEVICE
, detail
);
1921 ena
= fm_ena_generate(0, FM_ENA_FMT1
);
1922 if (type
== HCA_IBA_ERR
) {
1923 /* this is an error of its own */
1924 ena
= fm_ena_increment(ena
);
1927 ddi_fm_ereport_post(dip
, buf
, ena
, DDI_NOSLEEP
,
1928 FM_VERSION
, DATA_TYPE_UINT8
, FM_EREPORT_VERS0
, NULL
);
1933 * struct i_hca_acc_handle *
1934 * i_hca_get_acc_handle(struct i_hca_fm *hca_fm, ddi_acc_handle_t handle)
1937 * i_hca_get_acc_handle() returns ddi_acc_handle_t used for HCA FM.
1940 * hca_fm: pointer to HCA FM structure
1941 * handle: ddi_acc_handle_t
1944 * handle: pointer to ddi_acc_handle_t used for HCA FM
1947 * i_hca_get_acc_handle() can be called in user, kernel or interrupt
1950 static struct i_hca_acc_handle
*
1951 i_hca_get_acc_handle(struct i_hca_fm
*hca_fm
, ddi_acc_handle_t handle
)
1953 struct i_hca_acc_handle
*hdlp
;
1955 /* Retrieve the HCA FM access handle */
1956 mutex_enter(&hca_fm
->lock
);
1958 for (hdlp
= hca_fm
->hdl
; hdlp
!= NULL
; hdlp
= hdlp
->next
) {
1959 if (hdlp
->save_hdl
== handle
) {
1960 mutex_exit(&hca_fm
->lock
);
1965 mutex_exit(&hca_fm
->lock
);
1972 * i_hca_regs_map_setup(struct i_hca_fm *hca_fm, dev_info_t *dip,
1973 * uint_t rnumber, caddr_t *addrp, offset_t offset, offset_t len,
1974 * ddi_device_acc_attr_t *accattrp, ddi_acc_handle_t *handle)
1977 * i_hca_regs_map_setup() is a wrapper function of ddi_regs_map_setup(),
1978 * but allocates the HCA FM acc handle structure and initializes it.
1981 * hca_fm: pointer to HCA FM structure
1982 * dip: pointer to this device dev_info structure
1983 * rnumber: index number to the register address space set
1984 * addrp: platform-dependent value (same as ddi_regs_map_setup())
1985 * offset: offset into the register address space
1986 * len: address space length to be mapped
1987 * accattrp: pointer to device access attribute structure
1988 * handle: pointer to ddi_acc_handle_t used for HCA FM
1991 * ddi function status value which are:
1994 * DDI_ME_RNUMBER_RNGE
1995 * DDI_REGS_ACC_CONFLICT
1998 * i_hca_regs_map_setup() can be called in user or kernel context only.
2001 i_hca_regs_map_setup(struct i_hca_fm
*hca_fm
, dev_info_t
*dip
, uint_t rnumber
,
2002 caddr_t
*addrp
, offset_t offset
, offset_t len
,
2003 ddi_device_acc_attr_t
*accattrp
, ddi_acc_handle_t
*handle
)
2006 struct i_hca_acc_handle
*handlep
, *hdlp
, *last
;
2008 /* Allocate an access handle */
2009 if ((status
= ddi_regs_map_setup(dip
, rnumber
, addrp
, offset
,
2010 len
, accattrp
, handle
)) != DDI_SUCCESS
) {
2014 /* Allocate HCA FM acc handle structure */
2015 handlep
= kmem_cache_alloc(hca_fm
->fm_acc_cache
, KM_SLEEP
);
2017 /* Initialize fields */
2018 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*handlep
))
2019 handlep
->next
= NULL
;
2020 handlep
->save_hdl
= (*handle
);
2021 handlep
->thread_cnt
= 0;
2022 mutex_init(&handlep
->lock
, NULL
, MUTEX_DRIVER
, NULL
);
2024 /* Register this handle */
2025 mutex_enter(&hca_fm
->lock
);
2026 for (last
= hdlp
= hca_fm
->hdl
; hdlp
!= NULL
; hdlp
= hdlp
->next
) {
2030 hca_fm
->hdl
= handlep
;
2032 last
->next
= handlep
;
2034 mutex_exit(&hca_fm
->lock
);
2042 * i_hca_regs_map_free(struct i_hca_fm *hca_fm, ddi_acc_handle_t *handlep)
2045 * i_hca_regs_map_setup() is a wrapper function of ddi_regs_map_free(),
2046 * and frees the HCA FM acc handle structure allocated by
2047 * i_hca_regs_map_setup().
2050 * hca_fm: pointer to HCA FM structure
2051 * handle: pointer to ddi_acc_handle_t used for HCA FM
2057 * i_hca_regs_map_free() can be called in user or kernel context only.
2059 * Note that the handle passed to i_hca_regs_map_free() is NULL-cleared
2060 * after this function is called.
2063 i_hca_regs_map_free(struct i_hca_fm
*hca_fm
, ddi_acc_handle_t
*handle
)
2065 struct i_hca_acc_handle
*handlep
, *hdlp
, *prev
;
2067 /* De-register this handle */
2068 mutex_enter(&hca_fm
->lock
);
2069 for (prev
= hdlp
= hca_fm
->hdl
; hdlp
!= NULL
; hdlp
= hdlp
->next
) {
2070 if (hdlp
->save_hdl
== *handle
)
2074 ASSERT(prev
!= NULL
&& hdlp
!= NULL
);
2076 prev
->next
= hdlp
->next
;
2078 hca_fm
->hdl
= hdlp
->next
;
2081 mutex_exit(&hca_fm
->lock
);
2083 mutex_destroy(&handlep
->lock
);
2084 handlep
->save_hdl
= NULL
;
2085 kmem_cache_free(hca_fm
->fm_acc_cache
, handlep
);
2087 /* Release this handle */
2088 ddi_regs_map_free(handle
);
2095 * i_hca_pci_config_setup(struct i_hca_fm *hca_fm, dev_info_t *dip,
2096 * ddi_acc_handle_t *handle, boolean_t fm_protect)
2099 * i_hca_pci_config_setup() is a wrapper function of pci_config_setup(),
2100 * but allocates the HCA FM acc handle structure and initializes it.
2103 * hca_fm: pointer to HCA FM structure
2104 * dip: pointer to this device dev_info structure
2105 * handle: pointer to ddi_acc_handle_t used for HCA PCI config space
2107 * fm_protect: flag to tell if an fma-protected access handle should
2111 * ddi function status value which are:
2116 * i_hca_pci_config_setup() can be called in user or kernel context only.
2119 i_hca_pci_config_setup(struct i_hca_fm
*hca_fm
, dev_info_t
*dip
,
2120 ddi_acc_handle_t
*handle
)
2123 struct i_hca_acc_handle
*handlep
, *hdlp
, *last
;
2125 /* Allocate an access handle */
2126 if ((status
= pci_config_setup(dip
, handle
)) != DDI_SUCCESS
) {
2130 /* Allocate HCA FM acc handle structure */
2131 handlep
= kmem_cache_alloc(hca_fm
->fm_acc_cache
, KM_SLEEP
);
2133 /* Initialize fields */
2134 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*handlep
))
2135 handlep
->next
= NULL
;
2136 handlep
->save_hdl
= (*handle
);
2137 handlep
->thread_cnt
= 0;
2138 mutex_init(&handlep
->lock
, NULL
, MUTEX_DRIVER
, NULL
);
2140 /* Register this handle */
2141 mutex_enter(&hca_fm
->lock
);
2142 for (last
= hdlp
= hca_fm
->hdl
; hdlp
!= NULL
; hdlp
= hdlp
->next
) {
2146 hca_fm
->hdl
= handlep
;
2148 last
->next
= handlep
;
2150 mutex_exit(&hca_fm
->lock
);
2158 * i_hca_pci_config_teardown(struct i_hca_fm *hca_fm,
2159 * ddi_acc_handle_t *handlep)
2162 * i_hca_pci_config_teardown() is a wrapper function of
2163 * pci_config_teardown(), and frees the HCA FM acc handle structure
2164 * allocated by i_hca_pci_config_setup().
2167 * hca_fm: pointer to HCA FM structure
2168 * handle: pointer to ddi_acc_handle_t used for HCA FM
2174 * i_hca_pci_config_teardown() can be called in user or kernel context
2177 * Note that the handle passed to i_hca_pci_config_teardown() is NULL-cleared
2178 * after this function is called.
2181 i_hca_pci_config_teardown(struct i_hca_fm
*hca_fm
, ddi_acc_handle_t
*handle
)
2183 struct i_hca_acc_handle
*handlep
, *hdlp
, *prev
;
2185 /* De-register this handle */
2186 mutex_enter(&hca_fm
->lock
);
2187 for (prev
= hdlp
= hca_fm
->hdl
; hdlp
!= NULL
; hdlp
= hdlp
->next
) {
2188 if (hdlp
->save_hdl
== *handle
)
2192 ASSERT(prev
!= NULL
&& hdlp
!= NULL
);
2194 prev
->next
= hdlp
->next
;
2196 hca_fm
->hdl
= hdlp
->next
;
2199 mutex_exit(&hca_fm
->lock
);
2201 mutex_destroy(&handlep
->lock
);
2202 handlep
->save_hdl
= NULL
;
2203 kmem_cache_free(hca_fm
->fm_acc_cache
, handlep
);
2205 /* Release this handle */
2206 pci_config_teardown(handle
);
2213 * i_hca_pio_start(dev_info_t *dip, struct i_acc_handle *handle,
2214 * struct i_hca_fm_test *tst)
2217 * i_hca_pio_start() is one of a pair of HCA FM fuctions for PIO, which
2218 * should be called before HCA drivers issue PIOs against I/O space.
2219 * See HCA FM comments at the beginning of this file in detail.
2222 * dip: pointer to this device dev_info structure
2223 * handle: pointer to ddi_acc_handle_t used for HCA FM
2224 * tst: pointer to HCA FM function test structure. If the structure
2225 * is not used, the NULL value must be passed instead.
2228 * error status showing whether or not this error can retry
2229 * HCA_PIO_OK No HW errors
2230 * HCA_PIO_TRANSIENT This error could be transient
2231 * HCA_PIO_PERSISTENT This error is persistent
2234 * i_hca_pio_start() can be called in user, kernel or interrupt context.
2238 i_hca_pio_start(dev_info_t
*dip
, struct i_hca_acc_handle
*hdlp
,
2239 struct i_hca_fm_test
*tst
)
2241 ddi_fm_error_t derr
;
2243 /* Count up the number of threads issuing this PIO */
2244 mutex_enter(&hdlp
->lock
);
2246 mutex_exit(&hdlp
->lock
);
2248 /* Get the PIO error via FMA */
2249 ddi_fm_acc_err_get(fm_acc_hdl(hdlp
), &derr
, DDI_FME_VERSION
);
2252 /* Trigger PIO errors */
2253 if (tst
!= NULL
&& tst
->trigger
& HCA_TEST_START
) {
2254 (*tst
->pio_injection
)(tst
, &derr
);
2256 #endif /* FMA_TEST */
2258 switch (derr
.fme_status
) {
2260 /* Not have to clear the fma error log */
2261 return (HCA_PIO_OK
);
2263 case DDI_FM_NONFATAL
:
2264 /* Now clear this error */
2265 ddi_fm_acc_err_clear(fm_acc_hdl(hdlp
), DDI_FME_VERSION
);
2267 /* Log this error and notify it as a persistent error */
2268 ddi_fm_service_impact(dip
, DDI_SERVICE_LOST
);
2269 return (HCA_PIO_PERSISTENT
);
2271 /* In theory, this shouldn't happen */
2273 case DDI_FM_UNKNOWN
:
2275 cmn_err(CE_WARN
, "Unknown HCA HW error status (%d)",
2277 /* Return this as a persistent error */
2278 return (HCA_PIO_PERSISTENT
);
2285 * i_hca_pio_end(dev_info_t *dip, ddi_acc_handle_t handle, int *cnt,
2286 * struct i_hca_fm_test *tst)
2289 * i_hca_pio_end() is the other of a pair of HCA FM fuctions for PIO,
2290 * which should be called after HCA drivers issue PIOs against I/O space.
2291 * See HCA FM comments at the beginning of this file in detail.
2294 * dip: pointer to this device dev_info structure
2295 * handle: pointer to ddi_acc_handle_t used for HCA FM
2296 * cnt: pointer to the counter variable which holds the nubmer of retry
2297 * when a HW error is detected.
2298 * tst: pointer to HCA FM function test structure. If the structure
2299 * is not used, the NULL value must be passed instead.
2302 * error status showing whether or not this error can retry
2303 * HCA_PIO_OK No HW errors
2304 * HCA_PIO_TRANSIENT This error could be transient
2305 * HCA_PIO_PERSISTENT This error is persistent
2308 * i_hca_pio_end() can be called in user, kernel or interrupt context.
2312 i_hca_pio_end(dev_info_t
*dip
, struct i_hca_acc_handle
*hdlp
, int *cnt
,
2313 struct i_hca_fm_test
*tst
)
2315 ddi_fm_error_t derr
;
2317 /* Get the PIO error via FMA */
2318 ddi_fm_acc_err_get(fm_acc_hdl(hdlp
), &derr
, DDI_FME_VERSION
);
2321 /* Trigger PIO errors */
2322 if (tst
!= NULL
&& tst
->trigger
& HCA_TEST_END
) {
2323 (*tst
->pio_injection
)(tst
, &derr
);
2325 #endif /* FMA_TEST */
2327 /* Evaluate the PIO error */
2328 switch (derr
.fme_status
) {
2330 /* Count down the number of threads issuing this PIO */
2331 mutex_enter(&hdlp
->lock
);
2333 mutex_exit(&hdlp
->lock
);
2335 /* Not have to clear the fma error log */
2336 return (HCA_PIO_OK
);
2338 case DDI_FM_NONFATAL
:
2339 /* Now clear this error */
2340 ddi_fm_acc_err_clear(fm_acc_hdl(hdlp
), DDI_FME_VERSION
);
2343 * Check if this error comes from another thread running
2344 * with the same handle almost at the same time.
2346 mutex_enter(&hdlp
->lock
);
2347 if (hdlp
->thread_cnt
> 1) {
2348 /* Count down the number of threads */
2350 mutex_exit(&hdlp
->lock
);
2352 /* Return this as a persistent error */
2353 return (HCA_PIO_PERSISTENT
);
2355 mutex_exit(&hdlp
->lock
);
2357 /* Now determine if this error is persistent or not */
2358 if (--(*cnt
) >= 0) {
2359 return (HCA_PIO_TRANSIENT
);
2361 /* Count down the number of threads */
2362 mutex_enter(&hdlp
->lock
);
2364 mutex_exit(&hdlp
->lock
);
2365 return (HCA_PIO_PERSISTENT
);
2368 /* In theory, this shouldn't happen */
2370 case DDI_FM_UNKNOWN
:
2372 cmn_err(CE_WARN
, "Unknown HCA HW error status (%d)",
2374 /* Return this as a persistent error */
2375 return (HCA_PIO_PERSISTENT
);
2381 * HCA FM Test Interface
2383 * These functions should be used for any HCA drivers, but probably
2384 * customized for their own HW design and/or FM implementation.
2385 * Customized functins should have the driver name prefix such as
2386 * hermon_xxxx() and be defined separately but whose function should
2387 * call the common interface inside.
2391 static int test_num
; /* serial number */
2392 static kmutex_t i_hca_test_lock
; /* lock for serial numer */
2396 * i_hca_test_init(mod_hash_t **strHashp, mod_hash_t **idHashp)
2399 * i_hca_test_init() creates two hash tables, one of which is for string,
2400 * and the other of which is for ID, then saves pointers to arguments
2401 * passed. This function uses the mod_hash utilities to manage the
2402 * hash tables. About the mod_hash, see kernel/os/modhash.c.
2405 * strHashp: pointer to String hash table pointer
2406 * idHashp: pointer to ID hash table pointer
2412 * i_hca_test_init() can be called in user or kernel context only.
2415 i_hca_test_init(mod_hash_t
**strHashp
, mod_hash_t
**idHashp
)
2417 *idHashp
= mod_hash_create_idhash("HCA_FMA_id_hash",
2418 FMA_TEST_HASHSZ
, mod_hash_null_valdtor
);
2420 *strHashp
= mod_hash_create_strhash("HCA_FMA_test_hash",
2421 FMA_TEST_HASHSZ
, i_hca_test_free_item
);
2427 * i_hca_test_fini(mod_hash_t **strHashp, mod_hash_t **idHashp)
2430 * i_hca_test_fini() releases two hash tables used for HCA FM test.
2433 * strHashp: pointer to String hash table pointer
2434 * idHashp: pointer to ID hash table pointer
2440 * i_hca_test_fini() can be called in user, kernel or interrupt context.
2444 i_hca_test_fini(mod_hash_t
**strHashp
, mod_hash_t
**idHashp
)
2446 mod_hash_destroy_hash(*strHashp
);
2449 mod_hash_destroy_hash(*idHashp
);
2455 * struct i_hca_fm_test *
2456 * i_hca_test_register(char *filename, int linenum, int type,
2457 * void (*pio_injection)(struct i_hca_fm_test *, ddi_fm_error_t *),
2458 * void *private, mod_hash_t *strHash, mod_hash_t *idHash, int preTestNum)
2461 * i_hca_test_register() registers an HCA FM test item against HCA FM
2462 * function callings specified with the file name and the line number
2463 * (passed as the arguments).
2466 * filename: source file name where the function call is implemented
2467 * This value is usually a __FILE__ pre-defined macro.
2468 * linenum: line number where the function call is described in the
2469 * file specified above.
2470 * This value is usually a __LINE__ pre-defined macro.
2471 * type: HW error type
2472 * HCA_TEST_PIO pio error
2473 * HCA_TEST_IBA ib specific error
2474 * pio_injection: pio error injection callback function invoked when the
2475 * function specified above (with the file name and the
2476 * line number) is executed. If the function is not a PIO,
2477 * request, this parameter should be NULL.
2478 * private: the argument passed to either of injection functions when
2480 * strHashp: pointer to String hash table
2481 * idHashp: pointer to ID hash table
2482 * preTestNum: the index of the pre-defined testset for this test item.
2485 * pointer to HCA FM function test structure registered.
2488 * i_hca_test_register() can be called in user, kernel or interrupt
2492 static struct i_hca_fm_test
*
2493 i_hca_test_register(char *filename
, int linenum
, int type
,
2494 void (*pio_injection
)(struct i_hca_fm_test
*, ddi_fm_error_t
*),
2495 void *private, mod_hash_t
*strHash
, mod_hash_t
*idHash
, int preTestNum
)
2497 struct i_hca_fm_test
*t_item
;
2498 char key_buf
[255], *hash_key
;
2501 (void) sprintf(key_buf
, "%s:%d", filename
, linenum
);
2502 hash_key
= kmem_zalloc(strlen(key_buf
) + 1, KM_NOSLEEP
);
2504 if (hash_key
== NULL
)
2505 cmn_err(CE_PANIC
, "No memory for HCA FMA Test.");
2507 bcopy(key_buf
, hash_key
, strlen(key_buf
));
2509 status
= mod_hash_find(strHash
, (mod_hash_key_t
)hash_key
,
2510 (mod_hash_val_t
*)&t_item
);
2513 case MH_ERR_NOTFOUND
:
2514 t_item
= (struct i_hca_fm_test
*)
2515 kmem_alloc(sizeof (struct i_hca_fm_test
), KM_NOSLEEP
);
2517 cmn_err(CE_PANIC
, "No memory for HCA FMA Test.");
2519 /* Set the error number */
2520 mutex_enter(&i_hca_test_lock
);
2521 t_item
->num
= test_num
++;
2522 mutex_exit(&i_hca_test_lock
);
2524 /* Set type and other static information */
2525 t_item
->type
= type
;
2526 t_item
->line_num
= linenum
;
2527 t_item
->file_name
= filename
;
2528 t_item
->hash_key
= hash_key
;
2529 t_item
->private = private;
2530 t_item
->pio_injection
= pio_injection
;
2532 /* Set the pre-defined hermon test item */
2533 i_hca_test_set_item(preTestNum
, (struct i_hca_fm_test
*)t_item
);
2535 status
= mod_hash_insert(strHash
, (mod_hash_key_t
)
2536 hash_key
, (mod_hash_val_t
)t_item
);
2537 ASSERT(status
== 0);
2539 status
= mod_hash_insert(idHash
, (mod_hash_key_t
)
2540 (uintptr_t)t_item
->num
, (mod_hash_val_t
)t_item
);
2541 ASSERT(status
== 0);
2545 cmn_err(CE_PANIC
, "No memory for HCA FMA Test.");
2548 case MH_ERR_DUPLICATE
:
2549 cmn_err(CE_PANIC
, "HCA FMA Test Internal Error.");
2552 /* OK, this is already registered. */
2553 kmem_free(hash_key
, strlen(key_buf
) + 1);
2562 * i_hca_test_set_item(int num, struct i_hca_fm_test *t_item)
2565 * i_hca_test_set_item() is a private function used in
2566 * i_hca_test_register() above. This function sets the testset specified
2567 * (with the index number) to HCA FM function test structure.
2570 * num: index to test set (testset structure array)
2571 * t_item: pointer to HCA fM function test structure
2577 * i_hca_test_set_item() can be called in user, kernel, interrupt
2578 * context or hight interrupt context.
2582 i_hca_test_set_item(int num
, struct i_hca_fm_test
*t_item
)
2584 if (num
< 0 || num
>= sizeof (testset
) / sizeof (hermon_test_t
) ||
2585 testset
[num
].type
!= t_item
->type
) {
2586 t_item
->trigger
= testset
[0].trigger
;
2587 t_item
->errcnt
= testset
[0].errcnt
;
2591 /* Set the testsuite */
2592 t_item
->trigger
= testset
[num
].trigger
;
2593 t_item
->errcnt
= testset
[num
].errcnt
;
2599 * i_hca_test_free_item(mod_hash_val_t val)
2602 * i_hca_test_free_item() is a private function used to free HCA FM
2603 * function test structure when i_hca_test_fini() is called. This function
2604 * is registered as a destructor when the hash table is created in
2605 * i_hca_test_init().
2608 * val: pointer to the value stored in hash table (pointer to HCA FM
2609 * function test structure)
2615 * i_hca_test_free_item() can be called in user, kernel or interrupt
2620 i_hca_test_free_item(mod_hash_val_t val
)
2622 struct i_hca_fm_test
*t_item
= (struct i_hca_fm_test
*)val
;
2623 kmem_free(t_item
, sizeof (struct i_hca_fm_test
));
2625 #endif /* FMA_TEST */