4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1990-2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
32 #include <sys/sunddi.h>
33 #include <sys/ddi_impldefs.h>
34 #include <sys/cmn_err.h>
35 #include <sys/async.h>
36 #include <sys/sysiosbus.h>
37 #include <sys/sysioerr.h>
38 #include <sys/x_call.h>
39 #include <sys/machsystm.h>
40 #include <sys/sysmacros.h>
41 #include <sys/vmsystm.h>
42 #include <sys/cpu_module.h>
45 * Set the following variable in /etc/system to tell the kernel
46 * not to shutdown the machine if the temperature reaches
47 * the Thermal Warning limit.
52 * To indicate if the prom has the property of "thermal-interrupt".
54 static int thermal_interrupt_enabled
= 0;
57 #include <sys/starfire.h>
60 pc_translate_tgtid(caddr_t
, int, volatile uint64_t *);
63 pc_ittrans_cleanup(caddr_t
, volatile uint64_t *);
64 #endif /* _STARFIRE */
67 * adb debug_sysio_errs to 1 if you don't want your system to panic on
68 * sbus ue errors. adb sysio_err_flag to 0 if you don't want your system
69 * to check for sysio errors at all.
71 int sysio_err_flag
= 1;
72 uint_t debug_sysio_errs
= 0;
75 * bto_cnt = number of bus errors and timeouts allowed within bto_secs
76 * use /etc/system to change the bto_cnt to a very large number if
83 sysio_ue_intr(struct sbus_soft_state
*softsp
);
86 sysio_ce_intr(struct sbus_soft_state
*softsp
);
89 sbus_err_intr(struct sbus_soft_state
*softsp
);
92 sysio_log_ce_err(struct async_flt
*ecc
, char *unum
);
95 sysio_log_ue_err(struct async_flt
*ecc
, char *unum
);
98 sbus_clear_intr(struct sbus_soft_state
*softsp
, uint64_t *pafsr
);
101 sbus_log_error(struct sbus_soft_state
*softsp
, uint64_t *pafsr
, uint64_t *pafar
,
102 ushort_t id
, ushort_t inst
, int cleared
,
103 on_trap_data_t
*ontrap_data
);
106 sbus_check_bto(struct sbus_soft_state
*softsp
);
109 sbus_log_csr_error(struct async_flt
*aflt
, char *unum
);
112 sbus_ctrl_ecc_err(struct sbus_soft_state
*softsp
);
115 sysio_dis_err(struct sbus_soft_state
*softsp
);
118 sysio_init_err(struct sbus_soft_state
*softsp
);
121 sysio_thermal_warn_intr(struct sbus_soft_state
*softsp
);
123 static int sbus_pil
[] = {SBUS_UE_PIL
, SBUS_CE_PIL
, SBUS_ERR_PIL
, SBUS_PF_PIL
,
124 SBUS_THERMAL_PIL
, SBUS_PM_PIL
};
126 sysio_err_init(struct sbus_soft_state
*softsp
, caddr_t address
)
128 if (sysio_err_flag
== 0) {
129 cmn_err(CE_CONT
, "Warning: sysio errors not initialized\n");
130 return (DDI_SUCCESS
);
134 * Get the address of the already mapped-in sysio/sbus error registers.
135 * Simply add each registers offset to the already mapped in address
136 * that was retrieved from the device node's "address" property,
137 * and passed as an argument to this function.
139 * Define a macro for the pointer arithmetic ...
142 #define REG_ADDR(b, o) (uint64_t *)((caddr_t)(b) + (o))
144 softsp
->sysio_ecc_reg
= REG_ADDR(address
, OFF_SYSIO_ECC_REGS
);
145 softsp
->sysio_ue_reg
= REG_ADDR(address
, OFF_SYSIO_UE_REGS
);
146 softsp
->sysio_ce_reg
= REG_ADDR(address
, OFF_SYSIO_CE_REGS
);
147 softsp
->sbus_err_reg
= REG_ADDR(address
, OFF_SBUS_ERR_REGS
);
152 * create the interrupt-priorities property if it doesn't
153 * already exist to provide a hint as to the PIL level for
159 if (ddi_getproplen(DDI_DEV_T_ANY
, softsp
->dip
,
160 DDI_PROP_DONTPASS
, "interrupt-priorities",
161 &len
) != DDI_PROP_SUCCESS
) {
162 /* Create the interrupt-priorities property. */
163 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE
,
164 softsp
->dip
, "interrupt-priorities",
165 (int *)sbus_pil
, sizeof (sbus_pil
) / sizeof (int));
169 (void) ddi_add_intr(softsp
->dip
, 0, NULL
, NULL
,
170 (uint_t (*)())sysio_ue_intr
, (caddr_t
)softsp
);
171 (void) ddi_add_intr(softsp
->dip
, 1, NULL
, NULL
,
172 (uint_t (*)())sysio_ce_intr
, (caddr_t
)softsp
);
173 (void) ddi_add_intr(softsp
->dip
, 2, NULL
, NULL
,
174 (uint_t (*)())sbus_err_intr
, (caddr_t
)softsp
);
176 * If the thermal-interrupt property is in place,
177 * then register the thermal warning interrupt handler and
178 * program its mapping register
180 thermal_interrupt_enabled
= ddi_getprop(DDI_DEV_T_ANY
, softsp
->dip
,
181 DDI_PROP_DONTPASS
, "thermal-interrupt", -1);
183 if (thermal_interrupt_enabled
== 1) {
184 (void) ddi_add_intr(softsp
->dip
, 4, NULL
, NULL
,
185 (uint_t (*)())sysio_thermal_warn_intr
, (caddr_t
)softsp
);
188 bus_func_register(BF_TYPE_UE
, (busfunc_t
)sbus_ctrl_ecc_err
, softsp
);
189 bus_func_register(BF_TYPE_ERRDIS
, (busfunc_t
)sysio_dis_err
, softsp
);
191 (void) sysio_init_err(softsp
);
193 return (DDI_SUCCESS
);
197 sysio_err_resume_init(struct sbus_soft_state
*softsp
)
199 (void) sysio_init_err(softsp
);
200 return (DDI_SUCCESS
);
204 sysio_err_uninit(struct sbus_soft_state
*softsp
)
206 /* remove the interrupts from the interrupt list */
207 (void) sysio_dis_err(softsp
);
209 ddi_remove_intr(softsp
->dip
, 0, NULL
);
210 ddi_remove_intr(softsp
->dip
, 1, NULL
);
211 ddi_remove_intr(softsp
->dip
, 2, NULL
);
213 if (thermal_interrupt_enabled
== 1) {
214 ddi_remove_intr(softsp
->dip
, 4, NULL
);
217 bus_func_unregister(BF_TYPE_UE
, (busfunc_t
)sbus_ctrl_ecc_err
, softsp
);
218 bus_func_unregister(BF_TYPE_ERRDIS
, (busfunc_t
)sysio_dis_err
, softsp
);
220 return (DDI_SUCCESS
);
224 sysio_init_err(struct sbus_soft_state
*softsp
)
226 volatile uint64_t tmp_mondo_vec
, tmpreg
;
227 volatile uint64_t *mondo_vec_reg
;
228 uint_t cpu_id
, acpu_id
;
230 acpu_id
= intr_dist_cpuid();
232 * Program the mondo vector accordingly. This MUST be the
233 * last thing we do. Once we program the mondo, the device
234 * may begin to interrupt. Store it in the hardware reg.
236 mondo_vec_reg
= (uint64_t *)(softsp
->intr_mapping_reg
+ UE_ECC_MAPREG
);
239 cpu_id
= pc_translate_tgtid(softsp
->ittrans_cookie
, cpu_id
,
241 #endif /* _STARFIRE */
242 tmp_mondo_vec
= (cpu_id
<< INTERRUPT_CPU_FIELD
) | INTERRUPT_VALID
;
243 *mondo_vec_reg
= tmp_mondo_vec
;
245 mondo_vec_reg
= (uint64_t *)(softsp
->intr_mapping_reg
+ CE_ECC_MAPREG
);
248 cpu_id
= pc_translate_tgtid(softsp
->ittrans_cookie
, cpu_id
,
250 #endif /* _STARFIRE */
251 tmp_mondo_vec
= (cpu_id
<< INTERRUPT_CPU_FIELD
) | INTERRUPT_VALID
;
252 *mondo_vec_reg
= tmp_mondo_vec
;
255 (uint64_t *)(softsp
->intr_mapping_reg
+ SBUS_ERR_MAPREG
);
258 cpu_id
= pc_translate_tgtid(softsp
->ittrans_cookie
, cpu_id
,
260 #endif /* _STARFIRE */
262 tmp_mondo_vec
= (cpu_id
<< INTERRUPT_CPU_FIELD
) | INTERRUPT_VALID
;
263 *mondo_vec_reg
= tmp_mondo_vec
;
265 if (thermal_interrupt_enabled
== 1) {
266 mondo_vec_reg
= (softsp
->intr_mapping_reg
+ THERMAL_MAPREG
);
268 tmp_mondo_vec
= (cpu_id
<< INTERRUPT_CPU_FIELD
) |
270 *mondo_vec_reg
= tmp_mondo_vec
;
273 /* Flush store buffers */
274 tmpreg
= *softsp
->sbus_ctrl_reg
;
277 * XXX - This may already be set by the OBP.
279 tmpreg
= SYSIO_APCKEN
;
280 *softsp
->sysio_ctrl_reg
|= tmpreg
;
281 tmpreg
= (SECR_ECC_EN
| SECR_UE_INTEN
| SECR_CE_INTEN
);
282 *softsp
->sysio_ecc_reg
= tmpreg
;
283 tmpreg
= SB_CSR_ERRINT_EN
;
284 *softsp
->sbus_err_reg
|= tmpreg
;
286 /* Initialize timeout/bus error counter */
287 softsp
->bto_timestamp
= 0;
294 sysio_dis_err(struct sbus_soft_state
*softsp
)
296 volatile uint64_t tmpreg
;
297 volatile uint64_t *mondo_vec_reg
, *clear_vec_reg
;
299 *softsp
->sysio_ctrl_reg
&= ~SYSIO_APCKEN
;
300 *softsp
->sysio_ecc_reg
= 0;
301 *softsp
->sbus_err_reg
&= ~SB_CSR_ERRINT_EN
;
303 /* Flush store buffers */
304 tmpreg
= *softsp
->sbus_ctrl_reg
;
306 /* Unmap mapping registers */
307 mondo_vec_reg
= (softsp
->intr_mapping_reg
+ UE_ECC_MAPREG
);
308 clear_vec_reg
= (softsp
->clr_intr_reg
+ UE_ECC_CLEAR
);
313 /* do cleanup for starfire interrupt target translation */
314 pc_ittrans_cleanup(softsp
->ittrans_cookie
, mondo_vec_reg
);
315 #endif /* _STARFIRE */
319 mondo_vec_reg
= (softsp
->intr_mapping_reg
+ CE_ECC_MAPREG
);
320 clear_vec_reg
= (softsp
->clr_intr_reg
+ CE_ECC_CLEAR
);
325 /* Do cleanup for starfire interrupt target translation */
326 pc_ittrans_cleanup(softsp
->ittrans_cookie
, mondo_vec_reg
);
327 #endif /* _STARFIRE */
331 mondo_vec_reg
= (softsp
->intr_mapping_reg
+ SBUS_ERR_MAPREG
);
332 clear_vec_reg
= (softsp
->clr_intr_reg
+ SBUS_ERR_CLEAR
);
337 /* Do cleanup for starfire interrupt target translation */
338 pc_ittrans_cleanup(softsp
->ittrans_cookie
, mondo_vec_reg
);
339 #endif /* _STARFIRE */
343 /* Flush store buffers */
344 tmpreg
= *softsp
->sbus_ctrl_reg
;
350 * Gather information about the error into an async_flt structure, and then
351 * enqueue the error for reporting and processing and panic.
354 sysio_ue_intr(struct sbus_soft_state
*softsp
)
356 volatile uint64_t t_afsr
;
357 volatile uint64_t t_afar
;
358 volatile uint64_t *ue_reg
, *afar_reg
, *clear_reg
;
359 struct async_flt ecc
;
363 * Disable all further sbus errors, for this sbus instance, for
364 * what is guaranteed to be a fatal error. And grab any other cpus.
366 (void) sysio_dis_err(softsp
); /* disabled sysio errors */
369 * Then read and clear the afsr/afar and clear interrupt regs.
371 ue_reg
= (uint64_t *)softsp
->sysio_ue_reg
;
373 afar_reg
= (uint64_t *)ue_reg
+ 1;
377 clear_reg
= (softsp
->clr_intr_reg
+ UE_ECC_CLEAR
);
381 * The AFSR DW_OFFSET field contains the offset of the doubleword with
382 * the ECC error relative to the 64-byte aligned PA. We multiply by 8
383 * to convert to a byte offset, and then add this to flt_addr.
385 offset
= ((t_afsr
& SB_UE_AFSR_OFF
) >> SB_UE_DW_SHIFT
) * 8;
387 bzero(&ecc
, sizeof (ecc
));
388 ecc
.flt_id
= gethrtime();
389 ecc
.flt_stat
= t_afsr
;
390 ecc
.flt_addr
= P2ALIGN(t_afar
, 64) + offset
;
391 ecc
.flt_func
= sysio_log_ue_err
;
392 ecc
.flt_bus_id
= softsp
->upa_id
;
393 ecc
.flt_inst
= ddi_get_instance(softsp
->dip
);
394 ecc
.flt_status
= ECC_IOBUS
;
395 ecc
.flt_in_memory
= (pf_is_memory(t_afar
>> MMU_PAGESHIFT
)) ? 1: 0;
396 ecc
.flt_class
= BUS_FAULT
;
397 ecc
.flt_panic
= (debug_sysio_errs
== 0);
399 errorq_dispatch(ue_queue
, &ecc
, sizeof (ecc
), ecc
.flt_panic
);
402 * If the UE is in memory and fatal, save the fault info so the
403 * panic code will know to check for copyback errors.
405 if (ecc
.flt_panic
&& ecc
.flt_in_memory
)
409 * We must also check for other bus UE errors, and panic if
410 * any fatal ones are detected at this point.
412 if (bus_func_invoke(BF_TYPE_UE
) == BF_FATAL
)
416 cmn_err(CE_PANIC
, "Fatal Sbus%d UE Error", ecc
.flt_inst
);
418 return (DDI_INTR_CLAIMED
);
422 * callback logging function from the common error handling code
425 sysio_log_ue_err(struct async_flt
*ecc
, char *unum
)
427 uint64_t t_afsr
= ecc
->flt_stat
;
428 uint64_t t_afar
= ecc
->flt_addr
;
430 ushort_t id
= ecc
->flt_bus_id
;
431 ushort_t inst
= ecc
->flt_inst
;
433 if (t_afsr
& SB_UE_AFSR_P_PIO
) {
434 cmn_err(CE_WARN
, "SBus%d UE Primary Error from PIO: "
435 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
436 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
437 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, id
);
439 if (t_afsr
& SB_UE_AFSR_P_DRD
) {
440 cmn_err(CE_WARN
, "SBus%d UE Primary Error DMA read: "
441 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
442 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
443 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, unum
, id
);
445 if (t_afsr
& SB_UE_AFSR_P_DWR
) {
446 cmn_err(CE_WARN
, "SBus%d UE Primary Error DVMA write: "
447 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
448 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
449 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, unum
, id
);
452 * We should never hit the secondary error panics.
454 if (t_afsr
& SB_UE_AFSR_S_PIO
) {
455 cmn_err(CE_WARN
, "SBus%d UE Secondary Error from PIO: "
456 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
457 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
458 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, id
);
460 if (t_afsr
& SB_UE_AFSR_S_DRD
) {
461 cmn_err(CE_WARN
, "SBus%d UE Secondary Error DMA read: "
462 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
463 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
464 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, unum
, id
);
466 if (t_afsr
& SB_UE_AFSR_S_DWR
) {
467 cmn_err(CE_WARN
, "SBus%d UE Secondary Error DMA write: "
468 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
469 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
470 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, unum
, id
);
473 if ((debug_sysio_errs
) || (aft_verbose
)) {
474 (void) read_ecc_data(ecc
, 1, 0);
475 cmn_err(CE_CONT
, "\tOffset 0x%x, Size %d, UPA MID 0x%x\n",
476 (uint32_t)((t_afsr
& SB_UE_AFSR_OFF
) >> SB_UE_DW_SHIFT
),
477 (uint32_t)((t_afsr
& SB_UE_AFSR_SIZE
) >> SB_UE_SIZE_SHIFT
),
478 (uint32_t)((t_afsr
& SB_UE_AFSR_MID
) >> SB_UE_MID_SHIFT
));
483 * gather the information about the error, plus a pointer to
484 * the callback logging function, and call the generic ce_error handler.
487 sysio_ce_intr(struct sbus_soft_state
*softsp
)
489 volatile uint64_t t_afsr
;
490 volatile uint64_t t_afar
;
491 volatile uint64_t *afar_reg
, *clear_reg
, *ce_reg
;
492 struct async_flt ecc
;
495 ce_reg
= (uint64_t *)softsp
->sysio_ce_reg
;
497 afar_reg
= (uint64_t *)ce_reg
+ 1;
501 clear_reg
= (softsp
->clr_intr_reg
+ CE_ECC_CLEAR
);
505 * The AFSR DW_OFFSET field contains the offset of the doubleword with
506 * the ECC error relative to the 64-byte aligned PA. We multiply by 8
507 * to convert to a byte offset, and then add this to flt_addr.
509 offset
= ((t_afsr
& SB_UE_AFSR_OFF
) >> SB_UE_DW_SHIFT
) * 8;
511 bzero(&ecc
, sizeof (ecc
));
512 ecc
.flt_id
= gethrtime();
513 ecc
.flt_stat
= t_afsr
;
514 ecc
.flt_addr
= P2ALIGN(t_afar
, 64) + offset
;
515 ecc
.flt_func
= sysio_log_ce_err
;
516 ecc
.flt_bus_id
= softsp
->upa_id
;
517 ecc
.flt_inst
= ddi_get_instance(softsp
->dip
);
518 ecc
.flt_status
= ECC_IOBUS
;
520 ecc
.flt_synd
= (ushort_t
)((t_afsr
& SB_CE_AFSR_SYND
) >>
523 ecc
.flt_in_memory
= (pf_is_memory(t_afar
>> MMU_PAGESHIFT
)) ? 1: 0;
524 ecc
.flt_class
= BUS_FAULT
;
527 errorq_dispatch(ce_queue
, &ecc
, sizeof (ecc
), ERRORQ_ASYNC
);
529 return (DDI_INTR_CLAIMED
);
533 * callback logging function from the common error handling code
536 sysio_log_ce_err(struct async_flt
*ecc
, char *unum
)
538 uint64_t t_afsr
= ecc
->flt_stat
;
539 uint64_t t_afar
= ecc
->flt_addr
;
540 ushort_t id
= ecc
->flt_bus_id
;
541 ushort_t inst
= ecc
->flt_inst
;
542 int ce_verbose
= ce_verbose_memory
;
543 char *syndrome_str
= "!\tSyndrome 0x%x, Offset 0x%x, Size %d, "
546 if ((!ce_verbose_memory
) && (!debug_sysio_errs
))
549 if (t_afsr
& SB_CE_AFSR_P_PIO
) {
550 char *fmtstr
= "!SBus%d CE Primary Error from PIO: "
551 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
553 if ((debug_sysio_errs
) || (ce_verbose
> 1))
556 cmn_err(CE_CONT
, fmtstr
, inst
, (uint32_t)(t_afsr
>>32),
557 (uint32_t)t_afsr
, (uint32_t)(t_afar
>>32),
558 (uint32_t)t_afar
, id
);
560 if (t_afsr
& SB_CE_AFSR_P_DRD
) {
561 char *fmtstr
= "!SBus%d CE Primary Error DMA read: "
562 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
565 if ((debug_sysio_errs
) || (ce_verbose
> 1))
568 cmn_err(CE_CONT
, fmtstr
, inst
, (uint32_t)(t_afsr
>>32),
569 (uint32_t)t_afsr
, (uint32_t)(t_afar
>>32), (uint32_t)t_afar
,
572 if (t_afsr
& SB_CE_AFSR_P_DWR
) {
573 char *fmtstr
= "!SBus%d CE Primary Error DMA write: "
574 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d\n";
576 if ((debug_sysio_errs
) || (ce_verbose
> 1))
579 cmn_err(CE_CONT
, fmtstr
, inst
, (uint32_t)(t_afsr
>>32),
580 (uint32_t)t_afsr
, (uint32_t)(t_afar
>>32), (uint32_t)t_afar
,
584 if (t_afsr
& SB_CE_AFSR_S_PIO
) {
585 char *fmtstr
= "!SBus%d CE Secondary Error from PIO: "
586 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
588 if ((debug_sysio_errs
) || (ce_verbose
> 1))
591 cmn_err(CE_CONT
, fmtstr
, inst
, (uint32_t)(t_afsr
>>32),
592 (uint32_t)t_afsr
, (uint32_t)(t_afar
>>32), (uint32_t)t_afar
,
595 if (t_afsr
& SB_CE_AFSR_S_DRD
) {
596 char *fmtstr
= "!SBus%d CE Secondary Error DMA read: "
597 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
600 if ((debug_sysio_errs
) || (ce_verbose
> 1))
603 cmn_err(CE_CONT
, fmtstr
, inst
, (uint32_t)(t_afsr
>>32),
604 (uint32_t)t_afsr
, (uint32_t)(t_afar
>>32), (uint32_t)t_afar
,
607 if (t_afsr
& SB_CE_AFSR_S_DWR
) {
608 char *fmtstr
= "!SBus%d CE Secondary Error DMA write: "
609 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
612 if ((debug_sysio_errs
) || (ce_verbose
> 1))
615 cmn_err(CE_CONT
, fmtstr
,
616 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
617 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, unum
, id
);
620 if ((debug_sysio_errs
) || (ce_verbose
> 1))
623 cmn_err(CE_CONT
, syndrome_str
,
624 (uint32_t)((t_afsr
& SB_CE_AFSR_SYND
) >> SB_CE_SYND_SHIFT
),
625 (uint32_t)((t_afsr
& SB_CE_AFSR_OFF
) >> SB_CE_OFFSET_SHIFT
),
626 (uint32_t)((t_afsr
& SB_CE_AFSR_SIZE
) >> SB_CE_SIZE_SHIFT
),
627 (uint32_t)((t_afsr
& SB_CE_AFSR_MID
) >> SB_CE_MID_SHIFT
));
631 sbus_err_intr(struct sbus_soft_state
*softsp
)
633 volatile uint64_t t_afsr
;
634 volatile uint64_t t_afar
;
637 volatile uint64_t *afar_reg
;
638 on_trap_data_t
*otp
= softsp
->ontrap_data
;
640 t_afsr
= *softsp
->sbus_err_reg
;
641 afar_reg
= (uint64_t *)softsp
->sbus_err_reg
+ 1;
644 if (otp
== NULL
|| !(otp
->ot_prot
& OT_DATA_ACCESS
)) {
645 sbus_clear_intr(softsp
, (uint64_t *)&t_afsr
);
649 id
= (ushort_t
)softsp
->upa_id
;
650 inst
= (ushort_t
)ddi_get_instance(softsp
->dip
);
652 if (debug_sysio_errs
) {
653 if (otp
!= NULL
&& (otp
->ot_prot
& OT_DATA_ACCESS
))
654 otp
->ot_trap
|= OT_DATA_ACCESS
;
656 sbus_clear_intr(softsp
, (uint64_t *)&t_afsr
);
658 cmn_err(CE_CONT
, "SBus%d Error: AFSR 0x%08x.%08x "
659 "AFAR 0x%08x.%08x Id %d\n",
660 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
661 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, id
);
663 debug_enter("sbus_err_intr");
665 sbus_log_error(softsp
, (uint64_t *)&t_afsr
,
666 (uint64_t *)&t_afar
, id
, inst
, cleared
, otp
);
669 sbus_clear_intr(softsp
, (uint64_t *)&t_afsr
);
672 return (DDI_INTR_CLAIMED
);
676 sbus_clear_intr(struct sbus_soft_state
*softsp
, uint64_t *pafsr
)
678 volatile uint64_t *clear_reg
;
680 *softsp
->sbus_err_reg
= *pafsr
;
681 clear_reg
= (softsp
->clr_intr_reg
+ SBUS_ERR_CLEAR
);
686 sbus_log_error(struct sbus_soft_state
*softsp
, uint64_t *pafsr
, uint64_t *pafar
,
687 ushort_t id
, ushort_t inst
, int cleared
, on_trap_data_t
*otp
)
695 if (t_afsr
& SB_AFSR_P_LE
) {
697 sbus_clear_intr(softsp
, (uint64_t *)&t_afsr
);
698 cmn_err(CE_PANIC
, "SBus%d Primary Error Late PIO: "
699 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
700 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
701 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, id
);
703 if (t_afsr
& SB_AFSR_P_TO
) {
704 if (otp
!= NULL
&& (otp
->ot_prot
& OT_DATA_ACCESS
)) {
705 otp
->ot_trap
|= OT_DATA_ACCESS
;
708 if (sbus_check_bto(softsp
)) {
710 sbus_clear_intr(softsp
, (uint64_t *)&t_afsr
);
713 cmn_err(level
, "SBus%d Primary Error Timeout: "
714 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
715 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
716 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, id
);
718 if (t_afsr
& SB_AFSR_P_BERR
) {
719 if (otp
!= NULL
&& (otp
->ot_prot
& OT_DATA_ACCESS
)) {
720 otp
->ot_trap
|= OT_DATA_ACCESS
;
723 if (sbus_check_bto(softsp
)) {
725 sbus_clear_intr(softsp
, (uint64_t *)&t_afsr
);
728 cmn_err(level
, "SBus%d Primary Error Bus Error: "
729 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n",
730 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
731 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, id
);
734 if (t_afsr
& SB_AFSR_S_LE
) {
736 sbus_clear_intr(softsp
, (uint64_t *)&t_afsr
);
737 cmn_err(CE_PANIC
, "SBus%d Secondary Late PIO Error: "
738 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
739 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
740 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, id
);
742 if (t_afsr
& SB_AFSR_S_TO
) {
743 if (sbus_check_bto(softsp
)) {
745 sbus_clear_intr(softsp
, (uint64_t *)&t_afsr
);
748 cmn_err(level
, "SBus%d Secondary Timeout Error: "
749 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
750 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
751 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, id
);
753 if (t_afsr
& SB_AFSR_S_BERR
) {
754 if (sbus_check_bto(softsp
)) {
756 sbus_clear_intr(softsp
, (uint64_t *)&t_afsr
);
759 cmn_err(level
, "SBus%d Secondary Bus Error: "
760 "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
761 inst
, (uint32_t)(t_afsr
>>32), (uint32_t)t_afsr
,
762 (uint32_t)(t_afar
>>32), (uint32_t)t_afar
, id
);
768 sbus_check_bto(struct sbus_soft_state
*softsp
)
770 hrtime_t now
= gethrtime(); /* high PIL safe */
771 hrtime_t diff
= now
- softsp
->bto_timestamp
;
773 if (diff
> ((hrtime_t
)bto_secs
* NANOSEC
) || diff
< 0LL) {
775 * Reset error counter as this bus error has occurred
776 * after more than bto_secs duration.
778 softsp
->bto_timestamp
= now
;
781 if (softsp
->bto_ctr
++ >= bto_cnt
)
787 sbus_ctrl_ecc_err(struct sbus_soft_state
*softsp
)
792 t_sb_csr
= *softsp
->sbus_ctrl_reg
;
793 id
= (ushort_t
)softsp
->upa_id
;
794 inst
= (ushort_t
)ddi_get_instance(softsp
->dip
);
796 if (debug_sysio_errs
) {
797 cmn_err(CE_CONT
, "sbus_ctrl_ecc_error: SBus%d Control Reg "
798 "0x%016llx Id %d\n", inst
, (u_longlong_t
)t_sb_csr
, id
);
801 if (t_sb_csr
& (SB_CSR_DPERR_S14
|SB_CSR_DPERR_S13
|SB_CSR_DPERR_S3
|
802 SB_CSR_DPERR_S2
|SB_CSR_DPERR_S1
|SB_CSR_DPERR_S0
|SB_CSR_PIO_PERRS
)) {
803 struct async_flt aflt
;
805 *softsp
->sbus_ctrl_reg
= t_sb_csr
; /* clear error bits */
807 bzero(&aflt
, sizeof (aflt
));
808 aflt
.flt_id
= gethrtime();
809 aflt
.flt_stat
= t_sb_csr
;
810 aflt
.flt_func
= sbus_log_csr_error
;
811 aflt
.flt_bus_id
= id
;
812 aflt
.flt_inst
= inst
;
813 aflt
.flt_status
= ECC_IOBUS
;
814 aflt
.flt_class
= BUS_FAULT
;
817 errorq_dispatch(ue_queue
, &aflt
, sizeof (aflt
), aflt
.flt_panic
);
826 sbus_log_csr_error(struct async_flt
*aflt
, char *unum
)
828 uint64_t t_sb_csr
= aflt
->flt_stat
;
829 uint_t id
= aflt
->flt_bus_id
;
830 uint_t inst
= aflt
->flt_inst
;
833 * Print out SBus error information.
835 if (t_sb_csr
& SB_CSR_DPERR_S14
) {
837 "SBus%d Slot 14 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
838 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
840 if (t_sb_csr
& SB_CSR_DPERR_S13
) {
842 "SBus%d Slot 13 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
843 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
845 if (t_sb_csr
& SB_CSR_DPERR_S3
) {
847 "SBus%d Slot 3 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
848 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
850 if (t_sb_csr
& SB_CSR_DPERR_S2
) {
852 "SBus%d Slot 2 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
853 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
855 if (t_sb_csr
& SB_CSR_DPERR_S1
) {
857 "SBus%d Slot 1 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
858 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
860 if (t_sb_csr
& SB_CSR_DPERR_S0
) {
862 "SBus%d Slot 0 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
863 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
865 if (t_sb_csr
& SB_CSR_PPERR_S15
) {
867 "SBus%d Slot 15 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
868 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
870 if (t_sb_csr
& SB_CSR_PPERR_S14
) {
872 "SBus%d Slot 14 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
873 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
875 if (t_sb_csr
& SB_CSR_PPERR_S13
) {
877 "SBus%d Slot 13 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
878 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
880 if (t_sb_csr
& SB_CSR_PPERR_S3
) {
882 "SBus%d Slot 3 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
883 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
885 if (t_sb_csr
& SB_CSR_PPERR_S2
) {
887 "SBus%d Slot 2 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
888 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
890 if (t_sb_csr
& SB_CSR_PPERR_S1
) {
892 "SBus%d Slot 1 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
893 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
895 if (t_sb_csr
& SB_CSR_PPERR_S0
) {
897 "SBus%d Slot 0 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
898 inst
, (uint32_t)(t_sb_csr
>>32), (uint32_t)t_sb_csr
, id
);
903 * Sysio Thermal Warning interrupt handler
906 sysio_thermal_warn_intr(struct sbus_soft_state
*softsp
)
908 volatile uint64_t *clear_reg
;
909 volatile uint64_t tmp_mondo_vec
;
910 volatile uint64_t *mondo_vec_reg
;
911 const char thermal_warn_msg
[] =
912 "Severe over-temperature condition detected!";
915 * Take off the Thermal Warning interrupt and
916 * remove its interrupt handler.
918 mondo_vec_reg
= (softsp
->intr_mapping_reg
+ THERMAL_MAPREG
);
919 tmp_mondo_vec
= *mondo_vec_reg
;
920 tmp_mondo_vec
&= ~INTERRUPT_VALID
;
921 *mondo_vec_reg
= tmp_mondo_vec
;
923 ddi_remove_intr(softsp
->dip
, 4, NULL
);
925 clear_reg
= (softsp
->clr_intr_reg
+ THERMAL_CLEAR
);
929 cmn_err(CE_NOTE
, "OVEN TEST: %s", thermal_warn_msg
);
930 return (DDI_INTR_CLAIMED
);
933 cmn_err(CE_WARN
, "%s", thermal_warn_msg
);
934 cmn_err(CE_WARN
, "Powering down...");
939 * just in case do_shutdown() fails
941 (void) timeout((void(*)(void *))power_down
, NULL
,
942 thermal_powerdown_delay
* hz
);
944 return (DDI_INTR_CLAIMED
);