kernel: remove unused utsname_set_machine()
[unleashed.git] / usr / src / uts / sun4u / io / sysioerr.c
blobcb2ec1359bfff52cbda18c826cf3a735ef5fcd4c
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
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>
30 #include <sys/conf.h>
31 #include <sys/ddi.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.
49 int oven_test = 0;
52 * To indicate if the prom has the property of "thermal-interrupt".
54 static int thermal_interrupt_enabled = 0;
56 #ifdef _STARFIRE
57 #include <sys/starfire.h>
59 int
60 pc_translate_tgtid(caddr_t, int, volatile uint64_t *);
62 void
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
77 * it's a problem!
79 int bto_secs = 10;
80 int bto_cnt = 10;
82 static uint_t
83 sysio_ue_intr(struct sbus_soft_state *softsp);
85 static uint_t
86 sysio_ce_intr(struct sbus_soft_state *softsp);
88 static uint_t
89 sbus_err_intr(struct sbus_soft_state *softsp);
91 static void
92 sysio_log_ce_err(struct async_flt *ecc, char *unum);
94 static void
95 sysio_log_ue_err(struct async_flt *ecc, char *unum);
97 static void
98 sbus_clear_intr(struct sbus_soft_state *softsp, uint64_t *pafsr);
100 static void
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);
105 static int
106 sbus_check_bto(struct sbus_soft_state *softsp);
108 static void
109 sbus_log_csr_error(struct async_flt *aflt, char *unum);
111 static uint_t
112 sbus_ctrl_ecc_err(struct sbus_soft_state *softsp);
114 static uint_t
115 sysio_dis_err(struct sbus_soft_state *softsp);
117 static uint_t
118 sysio_init_err(struct sbus_soft_state *softsp);
120 static uint_t
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);
149 #undef REG_ADDR
152 * create the interrupt-priorities property if it doesn't
153 * already exist to provide a hint as to the PIL level for
154 * our interrupt.
157 int len;
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);
223 static uint_t
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);
237 cpu_id = acpu_id;
238 #ifdef _STARFIRE
239 cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
240 mondo_vec_reg);
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);
246 cpu_id = acpu_id;
247 #ifdef _STARFIRE
248 cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
249 mondo_vec_reg);
250 #endif /* _STARFIRE */
251 tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
252 *mondo_vec_reg = tmp_mondo_vec;
254 mondo_vec_reg =
255 (uint64_t *)(softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
256 cpu_id = acpu_id;
257 #ifdef _STARFIRE
258 cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
259 mondo_vec_reg);
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);
267 cpu_id = acpu_id;
268 tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) |
269 INTERRUPT_VALID;
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;
288 softsp->bto_ctr = 0;
290 return (0);
293 static uint_t
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);
310 *mondo_vec_reg = 0;
312 #ifdef _STARFIRE
313 /* do cleanup for starfire interrupt target translation */
314 pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
315 #endif /* _STARFIRE */
317 *clear_vec_reg = 0;
319 mondo_vec_reg = (softsp->intr_mapping_reg + CE_ECC_MAPREG);
320 clear_vec_reg = (softsp->clr_intr_reg + CE_ECC_CLEAR);
322 *mondo_vec_reg = 0;
324 #ifdef _STARFIRE
325 /* Do cleanup for starfire interrupt target translation */
326 pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
327 #endif /* _STARFIRE */
329 *clear_vec_reg = 0;
331 mondo_vec_reg = (softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
332 clear_vec_reg = (softsp->clr_intr_reg + SBUS_ERR_CLEAR);
334 *mondo_vec_reg = 0;
336 #ifdef _STARFIRE
337 /* Do cleanup for starfire interrupt target translation */
338 pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
339 #endif /* _STARFIRE */
341 *clear_vec_reg = 0;
343 /* Flush store buffers */
344 tmpreg = *softsp->sbus_ctrl_reg;
346 return (BF_NONE);
350 * Gather information about the error into an async_flt structure, and then
351 * enqueue the error for reporting and processing and panic.
353 static uint_t
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;
360 uint64_t offset;
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;
372 t_afsr = *ue_reg;
373 afar_reg = (uint64_t *)ue_reg + 1;
374 t_afar = *afar_reg;
375 *ue_reg = t_afsr;
377 clear_reg = (softsp->clr_intr_reg + UE_ECC_CLEAR);
378 *clear_reg = 0;
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)
406 panic_aflt = ecc;
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)
413 ecc.flt_panic = 1;
415 if (ecc.flt_panic)
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
424 static void
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.
486 static uint_t
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;
493 uint64_t offset;
495 ce_reg = (uint64_t *)softsp->sysio_ce_reg;
496 t_afsr = *ce_reg;
497 afar_reg = (uint64_t *)ce_reg + 1;
498 t_afar = *afar_reg;
499 *ce_reg = t_afsr;
501 clear_reg = (softsp->clr_intr_reg + CE_ECC_CLEAR);
502 *clear_reg = 0;
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) >>
521 SB_CE_SYND_SHIFT);
523 ecc.flt_in_memory = (pf_is_memory(t_afar >> MMU_PAGESHIFT)) ? 1: 0;
524 ecc.flt_class = BUS_FAULT;
526 ce_scrub(&ecc);
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
535 static void
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, "
544 "UPA MID 0x%x\n";
546 if ((!ce_verbose_memory) && (!debug_sysio_errs))
547 return;
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))
554 fmtstr++;
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 "
563 "Id %d\n";
565 if ((debug_sysio_errs) || (ce_verbose > 1))
566 fmtstr++;
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,
570 unum, id);
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))
577 fmtstr++;
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,
581 unum, id);
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))
589 fmtstr++;
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,
593 id);
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 "
598 "Id %d\n";
600 if ((debug_sysio_errs) || (ce_verbose > 1))
601 fmtstr++;
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,
605 unum, id);
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 "
610 "Id %d\n";
612 if ((debug_sysio_errs) || (ce_verbose > 1))
613 fmtstr++;
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))
621 syndrome_str++;
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));
630 static uint_t
631 sbus_err_intr(struct sbus_soft_state *softsp)
633 volatile uint64_t t_afsr;
634 volatile uint64_t t_afar;
635 ushort_t id, inst;
636 int cleared = 0;
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;
642 t_afar = *afar_reg;
644 if (otp == NULL || !(otp->ot_prot & OT_DATA_ACCESS)) {
645 sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
646 cleared = 1;
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;
655 if (!cleared)
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");
664 } else {
665 sbus_log_error(softsp, (uint64_t *)&t_afsr,
666 (uint64_t *)&t_afar, id, inst, cleared, otp);
668 if (!cleared) {
669 sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
672 return (DDI_INTR_CLAIMED);
675 static void
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);
682 *clear_reg = 0;
685 static void
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)
689 uint64_t t_afsr;
690 uint64_t t_afar;
691 int level = CE_WARN;
693 t_afsr = *pafsr;
694 t_afar = *pafar;
695 if (t_afsr & SB_AFSR_P_LE) {
696 if (!cleared)
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;
706 return;
708 if (sbus_check_bto(softsp)) {
709 if (!cleared)
710 sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
711 level = CE_PANIC;
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;
721 return;
723 if (sbus_check_bto(softsp)) {
724 if (!cleared)
725 sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
726 level = CE_PANIC;
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) {
735 if (!cleared)
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)) {
744 if (!cleared)
745 sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
746 level = CE_PANIC;
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)) {
755 if (!cleared)
756 sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
757 level = CE_PANIC;
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);
767 static int
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;
779 softsp->bto_ctr = 0;
781 if (softsp->bto_ctr++ >= bto_cnt)
782 return (1);
783 return (0);
786 static uint_t
787 sbus_ctrl_ecc_err(struct sbus_soft_state *softsp)
789 uint64_t t_sb_csr;
790 ushort_t id, inst;
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;
815 aflt.flt_panic = 1;
817 errorq_dispatch(ue_queue, &aflt, sizeof (aflt), aflt.flt_panic);
818 return (BF_FATAL);
821 return (BF_NONE);
824 /*ARGSUSED*/
825 static void
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) {
836 cmn_err(CE_WARN,
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) {
841 cmn_err(CE_WARN,
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) {
846 cmn_err(CE_WARN,
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) {
851 cmn_err(CE_WARN,
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) {
856 cmn_err(CE_WARN,
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) {
861 cmn_err(CE_WARN,
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) {
866 cmn_err(CE_WARN,
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) {
871 cmn_err(CE_WARN,
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) {
876 cmn_err(CE_WARN,
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) {
881 cmn_err(CE_WARN,
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) {
886 cmn_err(CE_WARN,
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) {
891 cmn_err(CE_WARN,
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) {
896 cmn_err(CE_WARN,
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
905 static uint_t
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);
926 *clear_reg = 0;
928 if (oven_test) {
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...");
936 do_shutdown();
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);