1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 1990-2002 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/conf.h>
31*0Sstevel@tonic-gate #include <sys/ddi.h>
32*0Sstevel@tonic-gate #include <sys/sunddi.h>
33*0Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
34*0Sstevel@tonic-gate #include <sys/cmn_err.h>
35*0Sstevel@tonic-gate #include <sys/async.h>
36*0Sstevel@tonic-gate #include <sys/sysiosbus.h>
37*0Sstevel@tonic-gate #include <sys/sysioerr.h>
38*0Sstevel@tonic-gate #include <sys/x_call.h>
39*0Sstevel@tonic-gate #include <sys/machsystm.h>
40*0Sstevel@tonic-gate #include <sys/sysmacros.h>
41*0Sstevel@tonic-gate #include <sys/vmsystm.h>
42*0Sstevel@tonic-gate #include <sys/cpu_module.h>
43*0Sstevel@tonic-gate
44*0Sstevel@tonic-gate /*
45*0Sstevel@tonic-gate * Set the following variable in /etc/system to tell the kernel
46*0Sstevel@tonic-gate * not to shutdown the machine if the temperature reaches
47*0Sstevel@tonic-gate * the Thermal Warning limit.
48*0Sstevel@tonic-gate */
49*0Sstevel@tonic-gate int oven_test = 0;
50*0Sstevel@tonic-gate
51*0Sstevel@tonic-gate /*
52*0Sstevel@tonic-gate * To indicate if the prom has the property of "thermal-interrupt".
53*0Sstevel@tonic-gate */
54*0Sstevel@tonic-gate static int thermal_interrupt_enabled = 0;
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate #ifdef _STARFIRE
57*0Sstevel@tonic-gate #include <sys/starfire.h>
58*0Sstevel@tonic-gate
59*0Sstevel@tonic-gate int
60*0Sstevel@tonic-gate pc_translate_tgtid(caddr_t, int, volatile uint64_t *);
61*0Sstevel@tonic-gate
62*0Sstevel@tonic-gate void
63*0Sstevel@tonic-gate pc_ittrans_cleanup(caddr_t, volatile uint64_t *);
64*0Sstevel@tonic-gate #endif /* _STARFIRE */
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gate /*
67*0Sstevel@tonic-gate * adb debug_sysio_errs to 1 if you don't want your system to panic on
68*0Sstevel@tonic-gate * sbus ue errors. adb sysio_err_flag to 0 if you don't want your system
69*0Sstevel@tonic-gate * to check for sysio errors at all.
70*0Sstevel@tonic-gate */
71*0Sstevel@tonic-gate int sysio_err_flag = 1;
72*0Sstevel@tonic-gate uint_t debug_sysio_errs = 0;
73*0Sstevel@tonic-gate
74*0Sstevel@tonic-gate /*
75*0Sstevel@tonic-gate * bto_cnt = number of bus errors and timeouts allowed within bto_secs
76*0Sstevel@tonic-gate * use /etc/system to change the bto_cnt to a very large number if
77*0Sstevel@tonic-gate * it's a problem!
78*0Sstevel@tonic-gate */
79*0Sstevel@tonic-gate int bto_secs = 10;
80*0Sstevel@tonic-gate int bto_cnt = 10;
81*0Sstevel@tonic-gate
82*0Sstevel@tonic-gate static uint_t
83*0Sstevel@tonic-gate sysio_ue_intr(struct sbus_soft_state *softsp);
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gate static uint_t
86*0Sstevel@tonic-gate sysio_ce_intr(struct sbus_soft_state *softsp);
87*0Sstevel@tonic-gate
88*0Sstevel@tonic-gate static uint_t
89*0Sstevel@tonic-gate sbus_err_intr(struct sbus_soft_state *softsp);
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gate static void
92*0Sstevel@tonic-gate sysio_log_ce_err(struct async_flt *ecc, char *unum);
93*0Sstevel@tonic-gate
94*0Sstevel@tonic-gate static void
95*0Sstevel@tonic-gate sysio_log_ue_err(struct async_flt *ecc, char *unum);
96*0Sstevel@tonic-gate
97*0Sstevel@tonic-gate static void
98*0Sstevel@tonic-gate sbus_clear_intr(struct sbus_soft_state *softsp, uint64_t *pafsr);
99*0Sstevel@tonic-gate
100*0Sstevel@tonic-gate static void
101*0Sstevel@tonic-gate sbus_log_error(struct sbus_soft_state *softsp, uint64_t *pafsr, uint64_t *pafar,
102*0Sstevel@tonic-gate ushort_t id, ushort_t inst, int cleared,
103*0Sstevel@tonic-gate on_trap_data_t *ontrap_data);
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gate static int
106*0Sstevel@tonic-gate sbus_check_bto(struct sbus_soft_state *softsp);
107*0Sstevel@tonic-gate
108*0Sstevel@tonic-gate static void
109*0Sstevel@tonic-gate sbus_log_csr_error(struct async_flt *aflt, char *unum);
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate static uint_t
112*0Sstevel@tonic-gate sbus_ctrl_ecc_err(struct sbus_soft_state *softsp);
113*0Sstevel@tonic-gate
114*0Sstevel@tonic-gate static uint_t
115*0Sstevel@tonic-gate sysio_dis_err(struct sbus_soft_state *softsp);
116*0Sstevel@tonic-gate
117*0Sstevel@tonic-gate static uint_t
118*0Sstevel@tonic-gate sysio_init_err(struct sbus_soft_state *softsp);
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gate static uint_t
121*0Sstevel@tonic-gate sysio_thermal_warn_intr(struct sbus_soft_state *softsp);
122*0Sstevel@tonic-gate
123*0Sstevel@tonic-gate static int sbus_pil[] = {SBUS_UE_PIL, SBUS_CE_PIL, SBUS_ERR_PIL, SBUS_PF_PIL,
124*0Sstevel@tonic-gate SBUS_THERMAL_PIL, SBUS_PM_PIL};
125*0Sstevel@tonic-gate int
sysio_err_init(struct sbus_soft_state * softsp,caddr_t address)126*0Sstevel@tonic-gate sysio_err_init(struct sbus_soft_state *softsp, caddr_t address)
127*0Sstevel@tonic-gate {
128*0Sstevel@tonic-gate if (sysio_err_flag == 0) {
129*0Sstevel@tonic-gate cmn_err(CE_CONT, "Warning: sysio errors not initialized\n");
130*0Sstevel@tonic-gate return (DDI_SUCCESS);
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate
133*0Sstevel@tonic-gate /*
134*0Sstevel@tonic-gate * Get the address of the already mapped-in sysio/sbus error registers.
135*0Sstevel@tonic-gate * Simply add each registers offset to the already mapped in address
136*0Sstevel@tonic-gate * that was retrieved from the device node's "address" property,
137*0Sstevel@tonic-gate * and passed as an argument to this function.
138*0Sstevel@tonic-gate *
139*0Sstevel@tonic-gate * Define a macro for the pointer arithmetic ...
140*0Sstevel@tonic-gate */
141*0Sstevel@tonic-gate
142*0Sstevel@tonic-gate #define REG_ADDR(b, o) (uint64_t *)((caddr_t)(b) + (o))
143*0Sstevel@tonic-gate
144*0Sstevel@tonic-gate softsp->sysio_ecc_reg = REG_ADDR(address, OFF_SYSIO_ECC_REGS);
145*0Sstevel@tonic-gate softsp->sysio_ue_reg = REG_ADDR(address, OFF_SYSIO_UE_REGS);
146*0Sstevel@tonic-gate softsp->sysio_ce_reg = REG_ADDR(address, OFF_SYSIO_CE_REGS);
147*0Sstevel@tonic-gate softsp->sbus_err_reg = REG_ADDR(address, OFF_SBUS_ERR_REGS);
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate #undef REG_ADDR
150*0Sstevel@tonic-gate
151*0Sstevel@tonic-gate /*
152*0Sstevel@tonic-gate * create the interrupt-priorities property if it doesn't
153*0Sstevel@tonic-gate * already exist to provide a hint as to the PIL level for
154*0Sstevel@tonic-gate * our interrupt.
155*0Sstevel@tonic-gate */
156*0Sstevel@tonic-gate {
157*0Sstevel@tonic-gate int len;
158*0Sstevel@tonic-gate
159*0Sstevel@tonic-gate if (ddi_getproplen(DDI_DEV_T_ANY, softsp->dip,
160*0Sstevel@tonic-gate DDI_PROP_DONTPASS, "interrupt-priorities",
161*0Sstevel@tonic-gate &len) != DDI_PROP_SUCCESS) {
162*0Sstevel@tonic-gate /* Create the interrupt-priorities property. */
163*0Sstevel@tonic-gate (void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
164*0Sstevel@tonic-gate softsp->dip, "interrupt-priorities",
165*0Sstevel@tonic-gate (int *)sbus_pil, sizeof (sbus_pil) / sizeof (int));
166*0Sstevel@tonic-gate }
167*0Sstevel@tonic-gate }
168*0Sstevel@tonic-gate
169*0Sstevel@tonic-gate (void) ddi_add_intr(softsp->dip, 0, NULL, NULL,
170*0Sstevel@tonic-gate (uint_t (*)())sysio_ue_intr, (caddr_t)softsp);
171*0Sstevel@tonic-gate (void) ddi_add_intr(softsp->dip, 1, NULL, NULL,
172*0Sstevel@tonic-gate (uint_t (*)())sysio_ce_intr, (caddr_t)softsp);
173*0Sstevel@tonic-gate (void) ddi_add_intr(softsp->dip, 2, NULL, NULL,
174*0Sstevel@tonic-gate (uint_t (*)())sbus_err_intr, (caddr_t)softsp);
175*0Sstevel@tonic-gate /*
176*0Sstevel@tonic-gate * If the thermal-interrupt property is in place,
177*0Sstevel@tonic-gate * then register the thermal warning interrupt handler and
178*0Sstevel@tonic-gate * program its mapping register
179*0Sstevel@tonic-gate */
180*0Sstevel@tonic-gate thermal_interrupt_enabled = ddi_getprop(DDI_DEV_T_ANY, softsp->dip,
181*0Sstevel@tonic-gate DDI_PROP_DONTPASS, "thermal-interrupt", -1);
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gate if (thermal_interrupt_enabled == 1) {
184*0Sstevel@tonic-gate (void) ddi_add_intr(softsp->dip, 4, NULL, NULL,
185*0Sstevel@tonic-gate (uint_t (*)())sysio_thermal_warn_intr, (caddr_t)softsp);
186*0Sstevel@tonic-gate }
187*0Sstevel@tonic-gate
188*0Sstevel@tonic-gate bus_func_register(BF_TYPE_UE, (busfunc_t)sbus_ctrl_ecc_err, softsp);
189*0Sstevel@tonic-gate bus_func_register(BF_TYPE_ERRDIS, (busfunc_t)sysio_dis_err, softsp);
190*0Sstevel@tonic-gate
191*0Sstevel@tonic-gate (void) sysio_init_err(softsp);
192*0Sstevel@tonic-gate
193*0Sstevel@tonic-gate return (DDI_SUCCESS);
194*0Sstevel@tonic-gate }
195*0Sstevel@tonic-gate
196*0Sstevel@tonic-gate int
sysio_err_resume_init(struct sbus_soft_state * softsp)197*0Sstevel@tonic-gate sysio_err_resume_init(struct sbus_soft_state *softsp)
198*0Sstevel@tonic-gate {
199*0Sstevel@tonic-gate (void) sysio_init_err(softsp);
200*0Sstevel@tonic-gate return (DDI_SUCCESS);
201*0Sstevel@tonic-gate }
202*0Sstevel@tonic-gate
203*0Sstevel@tonic-gate int
sysio_err_uninit(struct sbus_soft_state * softsp)204*0Sstevel@tonic-gate sysio_err_uninit(struct sbus_soft_state *softsp)
205*0Sstevel@tonic-gate {
206*0Sstevel@tonic-gate /* remove the interrupts from the interrupt list */
207*0Sstevel@tonic-gate (void) sysio_dis_err(softsp);
208*0Sstevel@tonic-gate
209*0Sstevel@tonic-gate ddi_remove_intr(softsp->dip, 0, NULL);
210*0Sstevel@tonic-gate ddi_remove_intr(softsp->dip, 1, NULL);
211*0Sstevel@tonic-gate ddi_remove_intr(softsp->dip, 2, NULL);
212*0Sstevel@tonic-gate
213*0Sstevel@tonic-gate if (thermal_interrupt_enabled == 1) {
214*0Sstevel@tonic-gate ddi_remove_intr(softsp->dip, 4, NULL);
215*0Sstevel@tonic-gate }
216*0Sstevel@tonic-gate
217*0Sstevel@tonic-gate bus_func_unregister(BF_TYPE_UE, (busfunc_t)sbus_ctrl_ecc_err, softsp);
218*0Sstevel@tonic-gate bus_func_unregister(BF_TYPE_ERRDIS, (busfunc_t)sysio_dis_err, softsp);
219*0Sstevel@tonic-gate
220*0Sstevel@tonic-gate return (DDI_SUCCESS);
221*0Sstevel@tonic-gate }
222*0Sstevel@tonic-gate
223*0Sstevel@tonic-gate static uint_t
sysio_init_err(struct sbus_soft_state * softsp)224*0Sstevel@tonic-gate sysio_init_err(struct sbus_soft_state *softsp)
225*0Sstevel@tonic-gate {
226*0Sstevel@tonic-gate volatile uint64_t tmp_mondo_vec, tmpreg;
227*0Sstevel@tonic-gate volatile uint64_t *mondo_vec_reg;
228*0Sstevel@tonic-gate uint_t cpu_id, acpu_id;
229*0Sstevel@tonic-gate
230*0Sstevel@tonic-gate acpu_id = intr_dist_cpuid();
231*0Sstevel@tonic-gate /*
232*0Sstevel@tonic-gate * Program the mondo vector accordingly. This MUST be the
233*0Sstevel@tonic-gate * last thing we do. Once we program the mondo, the device
234*0Sstevel@tonic-gate * may begin to interrupt. Store it in the hardware reg.
235*0Sstevel@tonic-gate */
236*0Sstevel@tonic-gate mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + UE_ECC_MAPREG);
237*0Sstevel@tonic-gate cpu_id = acpu_id;
238*0Sstevel@tonic-gate #ifdef _STARFIRE
239*0Sstevel@tonic-gate cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
240*0Sstevel@tonic-gate mondo_vec_reg);
241*0Sstevel@tonic-gate #endif /* _STARFIRE */
242*0Sstevel@tonic-gate tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
243*0Sstevel@tonic-gate *mondo_vec_reg = tmp_mondo_vec;
244*0Sstevel@tonic-gate
245*0Sstevel@tonic-gate mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + CE_ECC_MAPREG);
246*0Sstevel@tonic-gate cpu_id = acpu_id;
247*0Sstevel@tonic-gate #ifdef _STARFIRE
248*0Sstevel@tonic-gate cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
249*0Sstevel@tonic-gate mondo_vec_reg);
250*0Sstevel@tonic-gate #endif /* _STARFIRE */
251*0Sstevel@tonic-gate tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
252*0Sstevel@tonic-gate *mondo_vec_reg = tmp_mondo_vec;
253*0Sstevel@tonic-gate
254*0Sstevel@tonic-gate mondo_vec_reg =
255*0Sstevel@tonic-gate (uint64_t *)(softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
256*0Sstevel@tonic-gate cpu_id = acpu_id;
257*0Sstevel@tonic-gate #ifdef _STARFIRE
258*0Sstevel@tonic-gate cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
259*0Sstevel@tonic-gate mondo_vec_reg);
260*0Sstevel@tonic-gate #endif /* _STARFIRE */
261*0Sstevel@tonic-gate
262*0Sstevel@tonic-gate tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
263*0Sstevel@tonic-gate *mondo_vec_reg = tmp_mondo_vec;
264*0Sstevel@tonic-gate
265*0Sstevel@tonic-gate if (thermal_interrupt_enabled == 1) {
266*0Sstevel@tonic-gate mondo_vec_reg = (softsp->intr_mapping_reg + THERMAL_MAPREG);
267*0Sstevel@tonic-gate cpu_id = acpu_id;
268*0Sstevel@tonic-gate tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) |
269*0Sstevel@tonic-gate INTERRUPT_VALID;
270*0Sstevel@tonic-gate *mondo_vec_reg = tmp_mondo_vec;
271*0Sstevel@tonic-gate }
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gate /* Flush store buffers */
274*0Sstevel@tonic-gate tmpreg = *softsp->sbus_ctrl_reg;
275*0Sstevel@tonic-gate
276*0Sstevel@tonic-gate /*
277*0Sstevel@tonic-gate * XXX - This may already be set by the OBP.
278*0Sstevel@tonic-gate */
279*0Sstevel@tonic-gate tmpreg = SYSIO_APCKEN;
280*0Sstevel@tonic-gate *softsp->sysio_ctrl_reg |= tmpreg;
281*0Sstevel@tonic-gate tmpreg = (SECR_ECC_EN | SECR_UE_INTEN | SECR_CE_INTEN);
282*0Sstevel@tonic-gate *softsp->sysio_ecc_reg = tmpreg;
283*0Sstevel@tonic-gate tmpreg = SB_CSR_ERRINT_EN;
284*0Sstevel@tonic-gate *softsp->sbus_err_reg |= tmpreg;
285*0Sstevel@tonic-gate
286*0Sstevel@tonic-gate /* Initialize timeout/bus error counter */
287*0Sstevel@tonic-gate softsp->bto_timestamp = 0;
288*0Sstevel@tonic-gate softsp->bto_ctr = 0;
289*0Sstevel@tonic-gate
290*0Sstevel@tonic-gate return (0);
291*0Sstevel@tonic-gate }
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gate static uint_t
sysio_dis_err(struct sbus_soft_state * softsp)294*0Sstevel@tonic-gate sysio_dis_err(struct sbus_soft_state *softsp)
295*0Sstevel@tonic-gate {
296*0Sstevel@tonic-gate volatile uint64_t tmpreg;
297*0Sstevel@tonic-gate volatile uint64_t *mondo_vec_reg, *clear_vec_reg;
298*0Sstevel@tonic-gate
299*0Sstevel@tonic-gate *softsp->sysio_ctrl_reg &= ~SYSIO_APCKEN;
300*0Sstevel@tonic-gate *softsp->sysio_ecc_reg = 0;
301*0Sstevel@tonic-gate *softsp->sbus_err_reg &= ~SB_CSR_ERRINT_EN;
302*0Sstevel@tonic-gate
303*0Sstevel@tonic-gate /* Flush store buffers */
304*0Sstevel@tonic-gate tmpreg = *softsp->sbus_ctrl_reg;
305*0Sstevel@tonic-gate #ifdef lint
306*0Sstevel@tonic-gate tmpreg = tmpreg;
307*0Sstevel@tonic-gate #endif
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gate /* Unmap mapping registers */
310*0Sstevel@tonic-gate mondo_vec_reg = (softsp->intr_mapping_reg + UE_ECC_MAPREG);
311*0Sstevel@tonic-gate clear_vec_reg = (softsp->clr_intr_reg + UE_ECC_CLEAR);
312*0Sstevel@tonic-gate
313*0Sstevel@tonic-gate *mondo_vec_reg = 0;
314*0Sstevel@tonic-gate
315*0Sstevel@tonic-gate #ifdef _STARFIRE
316*0Sstevel@tonic-gate /* do cleanup for starfire interrupt target translation */
317*0Sstevel@tonic-gate pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
318*0Sstevel@tonic-gate #endif /* _STARFIRE */
319*0Sstevel@tonic-gate
320*0Sstevel@tonic-gate *clear_vec_reg = 0;
321*0Sstevel@tonic-gate
322*0Sstevel@tonic-gate mondo_vec_reg = (softsp->intr_mapping_reg + CE_ECC_MAPREG);
323*0Sstevel@tonic-gate clear_vec_reg = (softsp->clr_intr_reg + CE_ECC_CLEAR);
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gate *mondo_vec_reg = 0;
326*0Sstevel@tonic-gate
327*0Sstevel@tonic-gate #ifdef _STARFIRE
328*0Sstevel@tonic-gate /* Do cleanup for starfire interrupt target translation */
329*0Sstevel@tonic-gate pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
330*0Sstevel@tonic-gate #endif /* _STARFIRE */
331*0Sstevel@tonic-gate
332*0Sstevel@tonic-gate *clear_vec_reg = 0;
333*0Sstevel@tonic-gate
334*0Sstevel@tonic-gate mondo_vec_reg = (softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
335*0Sstevel@tonic-gate clear_vec_reg = (softsp->clr_intr_reg + SBUS_ERR_CLEAR);
336*0Sstevel@tonic-gate
337*0Sstevel@tonic-gate *mondo_vec_reg = 0;
338*0Sstevel@tonic-gate
339*0Sstevel@tonic-gate #ifdef _STARFIRE
340*0Sstevel@tonic-gate /* Do cleanup for starfire interrupt target translation */
341*0Sstevel@tonic-gate pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
342*0Sstevel@tonic-gate #endif /* _STARFIRE */
343*0Sstevel@tonic-gate
344*0Sstevel@tonic-gate *clear_vec_reg = 0;
345*0Sstevel@tonic-gate
346*0Sstevel@tonic-gate /* Flush store buffers */
347*0Sstevel@tonic-gate tmpreg = *softsp->sbus_ctrl_reg;
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gate return (BF_NONE);
350*0Sstevel@tonic-gate }
351*0Sstevel@tonic-gate
352*0Sstevel@tonic-gate /*
353*0Sstevel@tonic-gate * Gather information about the error into an async_flt structure, and then
354*0Sstevel@tonic-gate * enqueue the error for reporting and processing and panic.
355*0Sstevel@tonic-gate */
356*0Sstevel@tonic-gate static uint_t
sysio_ue_intr(struct sbus_soft_state * softsp)357*0Sstevel@tonic-gate sysio_ue_intr(struct sbus_soft_state *softsp)
358*0Sstevel@tonic-gate {
359*0Sstevel@tonic-gate volatile uint64_t t_afsr;
360*0Sstevel@tonic-gate volatile uint64_t t_afar;
361*0Sstevel@tonic-gate volatile uint64_t *ue_reg, *afar_reg, *clear_reg;
362*0Sstevel@tonic-gate struct async_flt ecc;
363*0Sstevel@tonic-gate uint64_t offset;
364*0Sstevel@tonic-gate
365*0Sstevel@tonic-gate /*
366*0Sstevel@tonic-gate * Disable all further sbus errors, for this sbus instance, for
367*0Sstevel@tonic-gate * what is guaranteed to be a fatal error. And grab any other cpus.
368*0Sstevel@tonic-gate */
369*0Sstevel@tonic-gate (void) sysio_dis_err(softsp); /* disabled sysio errors */
370*0Sstevel@tonic-gate
371*0Sstevel@tonic-gate /*
372*0Sstevel@tonic-gate * Then read and clear the afsr/afar and clear interrupt regs.
373*0Sstevel@tonic-gate */
374*0Sstevel@tonic-gate ue_reg = (uint64_t *)softsp->sysio_ue_reg;
375*0Sstevel@tonic-gate t_afsr = *ue_reg;
376*0Sstevel@tonic-gate afar_reg = (uint64_t *)ue_reg + 1;
377*0Sstevel@tonic-gate t_afar = *afar_reg;
378*0Sstevel@tonic-gate *ue_reg = t_afsr;
379*0Sstevel@tonic-gate
380*0Sstevel@tonic-gate clear_reg = (softsp->clr_intr_reg + UE_ECC_CLEAR);
381*0Sstevel@tonic-gate *clear_reg = 0;
382*0Sstevel@tonic-gate
383*0Sstevel@tonic-gate /*
384*0Sstevel@tonic-gate * The AFSR DW_OFFSET field contains the offset of the doubleword with
385*0Sstevel@tonic-gate * the ECC error relative to the 64-byte aligned PA. We multiply by 8
386*0Sstevel@tonic-gate * to convert to a byte offset, and then add this to flt_addr.
387*0Sstevel@tonic-gate */
388*0Sstevel@tonic-gate offset = ((t_afsr & SB_UE_AFSR_OFF) >> SB_UE_DW_SHIFT) * 8;
389*0Sstevel@tonic-gate
390*0Sstevel@tonic-gate bzero(&ecc, sizeof (ecc));
391*0Sstevel@tonic-gate ecc.flt_id = gethrtime();
392*0Sstevel@tonic-gate ecc.flt_stat = t_afsr;
393*0Sstevel@tonic-gate ecc.flt_addr = P2ALIGN(t_afar, 64) + offset;
394*0Sstevel@tonic-gate ecc.flt_func = sysio_log_ue_err;
395*0Sstevel@tonic-gate ecc.flt_bus_id = softsp->upa_id;
396*0Sstevel@tonic-gate ecc.flt_inst = ddi_get_instance(softsp->dip);
397*0Sstevel@tonic-gate ecc.flt_status = ECC_IOBUS;
398*0Sstevel@tonic-gate ecc.flt_in_memory = (pf_is_memory(t_afar >> MMU_PAGESHIFT)) ? 1: 0;
399*0Sstevel@tonic-gate ecc.flt_class = BUS_FAULT;
400*0Sstevel@tonic-gate ecc.flt_panic = (debug_sysio_errs == 0);
401*0Sstevel@tonic-gate
402*0Sstevel@tonic-gate errorq_dispatch(ue_queue, &ecc, sizeof (ecc), ecc.flt_panic);
403*0Sstevel@tonic-gate
404*0Sstevel@tonic-gate /*
405*0Sstevel@tonic-gate * If the UE is in memory and fatal, save the fault info so the
406*0Sstevel@tonic-gate * panic code will know to check for copyback errors.
407*0Sstevel@tonic-gate */
408*0Sstevel@tonic-gate if (ecc.flt_panic && ecc.flt_in_memory)
409*0Sstevel@tonic-gate panic_aflt = ecc;
410*0Sstevel@tonic-gate
411*0Sstevel@tonic-gate /*
412*0Sstevel@tonic-gate * We must also check for other bus UE errors, and panic if
413*0Sstevel@tonic-gate * any fatal ones are detected at this point.
414*0Sstevel@tonic-gate */
415*0Sstevel@tonic-gate if (bus_func_invoke(BF_TYPE_UE) == BF_FATAL)
416*0Sstevel@tonic-gate ecc.flt_panic = 1;
417*0Sstevel@tonic-gate
418*0Sstevel@tonic-gate if (ecc.flt_panic)
419*0Sstevel@tonic-gate cmn_err(CE_PANIC, "Fatal Sbus%d UE Error", ecc.flt_inst);
420*0Sstevel@tonic-gate
421*0Sstevel@tonic-gate return (DDI_INTR_CLAIMED);
422*0Sstevel@tonic-gate }
423*0Sstevel@tonic-gate
424*0Sstevel@tonic-gate /*
425*0Sstevel@tonic-gate * callback logging function from the common error handling code
426*0Sstevel@tonic-gate */
427*0Sstevel@tonic-gate static void
sysio_log_ue_err(struct async_flt * ecc,char * unum)428*0Sstevel@tonic-gate sysio_log_ue_err(struct async_flt *ecc, char *unum)
429*0Sstevel@tonic-gate {
430*0Sstevel@tonic-gate uint64_t t_afsr = ecc->flt_stat;
431*0Sstevel@tonic-gate uint64_t t_afar = ecc->flt_addr;
432*0Sstevel@tonic-gate
433*0Sstevel@tonic-gate ushort_t id = ecc->flt_bus_id;
434*0Sstevel@tonic-gate ushort_t inst = ecc->flt_inst;
435*0Sstevel@tonic-gate
436*0Sstevel@tonic-gate if (t_afsr & SB_UE_AFSR_P_PIO) {
437*0Sstevel@tonic-gate cmn_err(CE_WARN, "SBus%d UE Primary Error from PIO: "
438*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
439*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
440*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
441*0Sstevel@tonic-gate }
442*0Sstevel@tonic-gate if (t_afsr & SB_UE_AFSR_P_DRD) {
443*0Sstevel@tonic-gate cmn_err(CE_WARN, "SBus%d UE Primary Error DMA read: "
444*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
445*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
446*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
447*0Sstevel@tonic-gate }
448*0Sstevel@tonic-gate if (t_afsr & SB_UE_AFSR_P_DWR) {
449*0Sstevel@tonic-gate cmn_err(CE_WARN, "SBus%d UE Primary Error DVMA write: "
450*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
451*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
452*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
453*0Sstevel@tonic-gate }
454*0Sstevel@tonic-gate /*
455*0Sstevel@tonic-gate * We should never hit the secondary error panics.
456*0Sstevel@tonic-gate */
457*0Sstevel@tonic-gate if (t_afsr & SB_UE_AFSR_S_PIO) {
458*0Sstevel@tonic-gate cmn_err(CE_WARN, "SBus%d UE Secondary Error from PIO: "
459*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
460*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
461*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
462*0Sstevel@tonic-gate }
463*0Sstevel@tonic-gate if (t_afsr & SB_UE_AFSR_S_DRD) {
464*0Sstevel@tonic-gate cmn_err(CE_WARN, "SBus%d UE Secondary Error DMA read: "
465*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
466*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
467*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
468*0Sstevel@tonic-gate }
469*0Sstevel@tonic-gate if (t_afsr & SB_UE_AFSR_S_DWR) {
470*0Sstevel@tonic-gate cmn_err(CE_WARN, "SBus%d UE Secondary Error DMA write: "
471*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d",
472*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
473*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
474*0Sstevel@tonic-gate }
475*0Sstevel@tonic-gate
476*0Sstevel@tonic-gate if ((debug_sysio_errs) || (aft_verbose)) {
477*0Sstevel@tonic-gate (void) read_ecc_data(ecc, 1, 0);
478*0Sstevel@tonic-gate cmn_err(CE_CONT, "\tOffset 0x%x, Size %d, UPA MID 0x%x\n",
479*0Sstevel@tonic-gate (uint32_t)((t_afsr & SB_UE_AFSR_OFF) >> SB_UE_DW_SHIFT),
480*0Sstevel@tonic-gate (uint32_t)((t_afsr & SB_UE_AFSR_SIZE) >> SB_UE_SIZE_SHIFT),
481*0Sstevel@tonic-gate (uint32_t)((t_afsr & SB_UE_AFSR_MID) >> SB_UE_MID_SHIFT));
482*0Sstevel@tonic-gate }
483*0Sstevel@tonic-gate }
484*0Sstevel@tonic-gate
485*0Sstevel@tonic-gate /*
486*0Sstevel@tonic-gate * gather the information about the error, plus a pointer to
487*0Sstevel@tonic-gate * the callback logging function, and call the generic ce_error handler.
488*0Sstevel@tonic-gate */
489*0Sstevel@tonic-gate static uint_t
sysio_ce_intr(struct sbus_soft_state * softsp)490*0Sstevel@tonic-gate sysio_ce_intr(struct sbus_soft_state *softsp)
491*0Sstevel@tonic-gate {
492*0Sstevel@tonic-gate volatile uint64_t t_afsr;
493*0Sstevel@tonic-gate volatile uint64_t t_afar;
494*0Sstevel@tonic-gate volatile uint64_t *afar_reg, *clear_reg, *ce_reg;
495*0Sstevel@tonic-gate struct async_flt ecc;
496*0Sstevel@tonic-gate uint64_t offset;
497*0Sstevel@tonic-gate
498*0Sstevel@tonic-gate ce_reg = (uint64_t *)softsp->sysio_ce_reg;
499*0Sstevel@tonic-gate t_afsr = *ce_reg;
500*0Sstevel@tonic-gate afar_reg = (uint64_t *)ce_reg + 1;
501*0Sstevel@tonic-gate t_afar = *afar_reg;
502*0Sstevel@tonic-gate *ce_reg = t_afsr;
503*0Sstevel@tonic-gate
504*0Sstevel@tonic-gate clear_reg = (softsp->clr_intr_reg + CE_ECC_CLEAR);
505*0Sstevel@tonic-gate *clear_reg = 0;
506*0Sstevel@tonic-gate
507*0Sstevel@tonic-gate /*
508*0Sstevel@tonic-gate * The AFSR DW_OFFSET field contains the offset of the doubleword with
509*0Sstevel@tonic-gate * the ECC error relative to the 64-byte aligned PA. We multiply by 8
510*0Sstevel@tonic-gate * to convert to a byte offset, and then add this to flt_addr.
511*0Sstevel@tonic-gate */
512*0Sstevel@tonic-gate offset = ((t_afsr & SB_UE_AFSR_OFF) >> SB_UE_DW_SHIFT) * 8;
513*0Sstevel@tonic-gate
514*0Sstevel@tonic-gate bzero(&ecc, sizeof (ecc));
515*0Sstevel@tonic-gate ecc.flt_id = gethrtime();
516*0Sstevel@tonic-gate ecc.flt_stat = t_afsr;
517*0Sstevel@tonic-gate ecc.flt_addr = P2ALIGN(t_afar, 64) + offset;
518*0Sstevel@tonic-gate ecc.flt_func = sysio_log_ce_err;
519*0Sstevel@tonic-gate ecc.flt_bus_id = softsp->upa_id;
520*0Sstevel@tonic-gate ecc.flt_inst = ddi_get_instance(softsp->dip);
521*0Sstevel@tonic-gate ecc.flt_status = ECC_IOBUS;
522*0Sstevel@tonic-gate
523*0Sstevel@tonic-gate ecc.flt_synd = (ushort_t)((t_afsr & SB_CE_AFSR_SYND) >>
524*0Sstevel@tonic-gate SB_CE_SYND_SHIFT);
525*0Sstevel@tonic-gate
526*0Sstevel@tonic-gate ecc.flt_in_memory = (pf_is_memory(t_afar >> MMU_PAGESHIFT)) ? 1: 0;
527*0Sstevel@tonic-gate ecc.flt_class = BUS_FAULT;
528*0Sstevel@tonic-gate
529*0Sstevel@tonic-gate ce_scrub(&ecc);
530*0Sstevel@tonic-gate errorq_dispatch(ce_queue, &ecc, sizeof (ecc), ERRORQ_ASYNC);
531*0Sstevel@tonic-gate
532*0Sstevel@tonic-gate return (DDI_INTR_CLAIMED);
533*0Sstevel@tonic-gate }
534*0Sstevel@tonic-gate
535*0Sstevel@tonic-gate /*
536*0Sstevel@tonic-gate * callback logging function from the common error handling code
537*0Sstevel@tonic-gate */
538*0Sstevel@tonic-gate static void
sysio_log_ce_err(struct async_flt * ecc,char * unum)539*0Sstevel@tonic-gate sysio_log_ce_err(struct async_flt *ecc, char *unum)
540*0Sstevel@tonic-gate {
541*0Sstevel@tonic-gate uint64_t t_afsr = ecc->flt_stat;
542*0Sstevel@tonic-gate uint64_t t_afar = ecc->flt_addr;
543*0Sstevel@tonic-gate ushort_t id = ecc->flt_bus_id;
544*0Sstevel@tonic-gate ushort_t inst = ecc->flt_inst;
545*0Sstevel@tonic-gate int ce_verbose = ce_verbose_memory;
546*0Sstevel@tonic-gate char *syndrome_str = "!\tSyndrome 0x%x, Offset 0x%x, Size %d, "
547*0Sstevel@tonic-gate "UPA MID 0x%x\n";
548*0Sstevel@tonic-gate
549*0Sstevel@tonic-gate if ((!ce_verbose_memory) && (!debug_sysio_errs))
550*0Sstevel@tonic-gate return;
551*0Sstevel@tonic-gate
552*0Sstevel@tonic-gate if (t_afsr & SB_CE_AFSR_P_PIO) {
553*0Sstevel@tonic-gate char *fmtstr = "!SBus%d CE Primary Error from PIO: "
554*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
555*0Sstevel@tonic-gate
556*0Sstevel@tonic-gate if ((debug_sysio_errs) || (ce_verbose > 1))
557*0Sstevel@tonic-gate fmtstr++;
558*0Sstevel@tonic-gate
559*0Sstevel@tonic-gate cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
560*0Sstevel@tonic-gate (uint32_t)t_afsr, (uint32_t)(t_afar>>32),
561*0Sstevel@tonic-gate (uint32_t)t_afar, id);
562*0Sstevel@tonic-gate }
563*0Sstevel@tonic-gate if (t_afsr & SB_CE_AFSR_P_DRD) {
564*0Sstevel@tonic-gate char *fmtstr = "!SBus%d CE Primary Error DMA read: "
565*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
566*0Sstevel@tonic-gate "Id %d\n";
567*0Sstevel@tonic-gate
568*0Sstevel@tonic-gate if ((debug_sysio_errs) || (ce_verbose > 1))
569*0Sstevel@tonic-gate fmtstr++;
570*0Sstevel@tonic-gate
571*0Sstevel@tonic-gate cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
572*0Sstevel@tonic-gate (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
573*0Sstevel@tonic-gate unum, id);
574*0Sstevel@tonic-gate }
575*0Sstevel@tonic-gate if (t_afsr & SB_CE_AFSR_P_DWR) {
576*0Sstevel@tonic-gate char *fmtstr = "!SBus%d CE Primary Error DMA write: "
577*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s Id %d\n";
578*0Sstevel@tonic-gate
579*0Sstevel@tonic-gate if ((debug_sysio_errs) || (ce_verbose > 1))
580*0Sstevel@tonic-gate fmtstr++;
581*0Sstevel@tonic-gate
582*0Sstevel@tonic-gate cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
583*0Sstevel@tonic-gate (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
584*0Sstevel@tonic-gate unum, id);
585*0Sstevel@tonic-gate }
586*0Sstevel@tonic-gate
587*0Sstevel@tonic-gate if (t_afsr & SB_CE_AFSR_S_PIO) {
588*0Sstevel@tonic-gate char *fmtstr = "!SBus%d CE Secondary Error from PIO: "
589*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n";
590*0Sstevel@tonic-gate
591*0Sstevel@tonic-gate if ((debug_sysio_errs) || (ce_verbose > 1))
592*0Sstevel@tonic-gate fmtstr++;
593*0Sstevel@tonic-gate
594*0Sstevel@tonic-gate cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
595*0Sstevel@tonic-gate (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
596*0Sstevel@tonic-gate id);
597*0Sstevel@tonic-gate }
598*0Sstevel@tonic-gate if (t_afsr & SB_CE_AFSR_S_DRD) {
599*0Sstevel@tonic-gate char *fmtstr = "!SBus%d CE Secondary Error DMA read: "
600*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
601*0Sstevel@tonic-gate "Id %d\n";
602*0Sstevel@tonic-gate
603*0Sstevel@tonic-gate if ((debug_sysio_errs) || (ce_verbose > 1))
604*0Sstevel@tonic-gate fmtstr++;
605*0Sstevel@tonic-gate
606*0Sstevel@tonic-gate cmn_err(CE_CONT, fmtstr, inst, (uint32_t)(t_afsr>>32),
607*0Sstevel@tonic-gate (uint32_t)t_afsr, (uint32_t)(t_afar>>32), (uint32_t)t_afar,
608*0Sstevel@tonic-gate unum, id);
609*0Sstevel@tonic-gate }
610*0Sstevel@tonic-gate if (t_afsr & SB_CE_AFSR_S_DWR) {
611*0Sstevel@tonic-gate char *fmtstr = "!SBus%d CE Secondary Error DMA write: "
612*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x MemMod %s "
613*0Sstevel@tonic-gate "Id %d\n";
614*0Sstevel@tonic-gate
615*0Sstevel@tonic-gate if ((debug_sysio_errs) || (ce_verbose > 1))
616*0Sstevel@tonic-gate fmtstr++;
617*0Sstevel@tonic-gate
618*0Sstevel@tonic-gate cmn_err(CE_CONT, fmtstr,
619*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
620*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, unum, id);
621*0Sstevel@tonic-gate }
622*0Sstevel@tonic-gate
623*0Sstevel@tonic-gate if ((debug_sysio_errs) || (ce_verbose > 1))
624*0Sstevel@tonic-gate syndrome_str++;
625*0Sstevel@tonic-gate
626*0Sstevel@tonic-gate cmn_err(CE_CONT, syndrome_str,
627*0Sstevel@tonic-gate (uint32_t)((t_afsr & SB_CE_AFSR_SYND) >> SB_CE_SYND_SHIFT),
628*0Sstevel@tonic-gate (uint32_t)((t_afsr & SB_CE_AFSR_OFF) >> SB_CE_OFFSET_SHIFT),
629*0Sstevel@tonic-gate (uint32_t)((t_afsr & SB_CE_AFSR_SIZE) >> SB_CE_SIZE_SHIFT),
630*0Sstevel@tonic-gate (uint32_t)((t_afsr & SB_CE_AFSR_MID) >> SB_CE_MID_SHIFT));
631*0Sstevel@tonic-gate }
632*0Sstevel@tonic-gate
633*0Sstevel@tonic-gate static uint_t
sbus_err_intr(struct sbus_soft_state * softsp)634*0Sstevel@tonic-gate sbus_err_intr(struct sbus_soft_state *softsp)
635*0Sstevel@tonic-gate {
636*0Sstevel@tonic-gate volatile uint64_t t_afsr;
637*0Sstevel@tonic-gate volatile uint64_t t_afar;
638*0Sstevel@tonic-gate ushort_t id, inst;
639*0Sstevel@tonic-gate int cleared = 0;
640*0Sstevel@tonic-gate volatile uint64_t *afar_reg;
641*0Sstevel@tonic-gate on_trap_data_t *otp = softsp->ontrap_data;
642*0Sstevel@tonic-gate
643*0Sstevel@tonic-gate t_afsr = *softsp->sbus_err_reg;
644*0Sstevel@tonic-gate afar_reg = (uint64_t *)softsp->sbus_err_reg + 1;
645*0Sstevel@tonic-gate t_afar = *afar_reg;
646*0Sstevel@tonic-gate
647*0Sstevel@tonic-gate if (otp == NULL || !(otp->ot_prot & OT_DATA_ACCESS)) {
648*0Sstevel@tonic-gate sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
649*0Sstevel@tonic-gate cleared = 1;
650*0Sstevel@tonic-gate }
651*0Sstevel@tonic-gate
652*0Sstevel@tonic-gate id = (ushort_t)softsp->upa_id;
653*0Sstevel@tonic-gate inst = (ushort_t)ddi_get_instance(softsp->dip);
654*0Sstevel@tonic-gate
655*0Sstevel@tonic-gate if (debug_sysio_errs) {
656*0Sstevel@tonic-gate if (otp != NULL && (otp->ot_prot & OT_DATA_ACCESS))
657*0Sstevel@tonic-gate otp->ot_trap |= OT_DATA_ACCESS;
658*0Sstevel@tonic-gate if (!cleared)
659*0Sstevel@tonic-gate sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
660*0Sstevel@tonic-gate
661*0Sstevel@tonic-gate cmn_err(CE_CONT, "SBus%d Error: AFSR 0x%08x.%08x "
662*0Sstevel@tonic-gate "AFAR 0x%08x.%08x Id %d\n",
663*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
664*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
665*0Sstevel@tonic-gate
666*0Sstevel@tonic-gate debug_enter("sbus_err_intr");
667*0Sstevel@tonic-gate } else {
668*0Sstevel@tonic-gate sbus_log_error(softsp, (uint64_t *)&t_afsr,
669*0Sstevel@tonic-gate (uint64_t *)&t_afar, id, inst, cleared, otp);
670*0Sstevel@tonic-gate }
671*0Sstevel@tonic-gate if (!cleared) {
672*0Sstevel@tonic-gate sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
673*0Sstevel@tonic-gate }
674*0Sstevel@tonic-gate
675*0Sstevel@tonic-gate return (DDI_INTR_CLAIMED);
676*0Sstevel@tonic-gate }
677*0Sstevel@tonic-gate
678*0Sstevel@tonic-gate static void
sbus_clear_intr(struct sbus_soft_state * softsp,uint64_t * pafsr)679*0Sstevel@tonic-gate sbus_clear_intr(struct sbus_soft_state *softsp, uint64_t *pafsr)
680*0Sstevel@tonic-gate {
681*0Sstevel@tonic-gate volatile uint64_t *clear_reg;
682*0Sstevel@tonic-gate
683*0Sstevel@tonic-gate *softsp->sbus_err_reg = *pafsr;
684*0Sstevel@tonic-gate clear_reg = (softsp->clr_intr_reg + SBUS_ERR_CLEAR);
685*0Sstevel@tonic-gate *clear_reg = 0;
686*0Sstevel@tonic-gate }
687*0Sstevel@tonic-gate
688*0Sstevel@tonic-gate static void
sbus_log_error(struct sbus_soft_state * softsp,uint64_t * pafsr,uint64_t * pafar,ushort_t id,ushort_t inst,int cleared,on_trap_data_t * otp)689*0Sstevel@tonic-gate sbus_log_error(struct sbus_soft_state *softsp, uint64_t *pafsr, uint64_t *pafar,
690*0Sstevel@tonic-gate ushort_t id, ushort_t inst, int cleared, on_trap_data_t *otp)
691*0Sstevel@tonic-gate {
692*0Sstevel@tonic-gate uint64_t t_afsr;
693*0Sstevel@tonic-gate uint64_t t_afar;
694*0Sstevel@tonic-gate int level = CE_WARN;
695*0Sstevel@tonic-gate
696*0Sstevel@tonic-gate t_afsr = *pafsr;
697*0Sstevel@tonic-gate t_afar = *pafar;
698*0Sstevel@tonic-gate if (t_afsr & SB_AFSR_P_LE) {
699*0Sstevel@tonic-gate if (!cleared)
700*0Sstevel@tonic-gate sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
701*0Sstevel@tonic-gate cmn_err(CE_PANIC, "SBus%d Primary Error Late PIO: "
702*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
703*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
704*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
705*0Sstevel@tonic-gate }
706*0Sstevel@tonic-gate if (t_afsr & SB_AFSR_P_TO) {
707*0Sstevel@tonic-gate if (otp != NULL && (otp->ot_prot & OT_DATA_ACCESS)) {
708*0Sstevel@tonic-gate otp->ot_trap |= OT_DATA_ACCESS;
709*0Sstevel@tonic-gate return;
710*0Sstevel@tonic-gate }
711*0Sstevel@tonic-gate if (sbus_check_bto(softsp)) {
712*0Sstevel@tonic-gate if (!cleared)
713*0Sstevel@tonic-gate sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
714*0Sstevel@tonic-gate level = CE_PANIC;
715*0Sstevel@tonic-gate }
716*0Sstevel@tonic-gate cmn_err(level, "SBus%d Primary Error Timeout: "
717*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
718*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
719*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
720*0Sstevel@tonic-gate }
721*0Sstevel@tonic-gate if (t_afsr & SB_AFSR_P_BERR) {
722*0Sstevel@tonic-gate if (otp != NULL && (otp->ot_prot & OT_DATA_ACCESS)) {
723*0Sstevel@tonic-gate otp->ot_trap |= OT_DATA_ACCESS;
724*0Sstevel@tonic-gate return;
725*0Sstevel@tonic-gate }
726*0Sstevel@tonic-gate if (sbus_check_bto(softsp)) {
727*0Sstevel@tonic-gate if (!cleared)
728*0Sstevel@tonic-gate sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
729*0Sstevel@tonic-gate level = CE_PANIC;
730*0Sstevel@tonic-gate }
731*0Sstevel@tonic-gate cmn_err(level, "SBus%d Primary Error Bus Error: "
732*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d\n",
733*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
734*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
735*0Sstevel@tonic-gate }
736*0Sstevel@tonic-gate
737*0Sstevel@tonic-gate if (t_afsr & SB_AFSR_S_LE) {
738*0Sstevel@tonic-gate if (!cleared)
739*0Sstevel@tonic-gate sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
740*0Sstevel@tonic-gate cmn_err(CE_PANIC, "SBus%d Secondary Late PIO Error: "
741*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
742*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
743*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
744*0Sstevel@tonic-gate }
745*0Sstevel@tonic-gate if (t_afsr & SB_AFSR_S_TO) {
746*0Sstevel@tonic-gate if (sbus_check_bto(softsp)) {
747*0Sstevel@tonic-gate if (!cleared)
748*0Sstevel@tonic-gate sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
749*0Sstevel@tonic-gate level = CE_PANIC;
750*0Sstevel@tonic-gate }
751*0Sstevel@tonic-gate cmn_err(level, "SBus%d Secondary Timeout Error: "
752*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
753*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
754*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
755*0Sstevel@tonic-gate }
756*0Sstevel@tonic-gate if (t_afsr & SB_AFSR_S_BERR) {
757*0Sstevel@tonic-gate if (sbus_check_bto(softsp)) {
758*0Sstevel@tonic-gate if (!cleared)
759*0Sstevel@tonic-gate sbus_clear_intr(softsp, (uint64_t *)&t_afsr);
760*0Sstevel@tonic-gate level = CE_PANIC;
761*0Sstevel@tonic-gate }
762*0Sstevel@tonic-gate cmn_err(level, "SBus%d Secondary Bus Error: "
763*0Sstevel@tonic-gate "AFSR 0x%08x.%08x AFAR 0x%08x.%08x Id %d",
764*0Sstevel@tonic-gate inst, (uint32_t)(t_afsr>>32), (uint32_t)t_afsr,
765*0Sstevel@tonic-gate (uint32_t)(t_afar>>32), (uint32_t)t_afar, id);
766*0Sstevel@tonic-gate }
767*0Sstevel@tonic-gate }
768*0Sstevel@tonic-gate
769*0Sstevel@tonic-gate
770*0Sstevel@tonic-gate static int
sbus_check_bto(struct sbus_soft_state * softsp)771*0Sstevel@tonic-gate sbus_check_bto(struct sbus_soft_state *softsp)
772*0Sstevel@tonic-gate {
773*0Sstevel@tonic-gate hrtime_t now = gethrtime(); /* high PIL safe */
774*0Sstevel@tonic-gate hrtime_t diff = now - softsp->bto_timestamp;
775*0Sstevel@tonic-gate
776*0Sstevel@tonic-gate if (diff > ((hrtime_t)bto_secs * NANOSEC) || diff < 0LL) {
777*0Sstevel@tonic-gate /*
778*0Sstevel@tonic-gate * Reset error counter as this bus error has occurred
779*0Sstevel@tonic-gate * after more than bto_secs duration.
780*0Sstevel@tonic-gate */
781*0Sstevel@tonic-gate softsp->bto_timestamp = now;
782*0Sstevel@tonic-gate softsp->bto_ctr = 0;
783*0Sstevel@tonic-gate }
784*0Sstevel@tonic-gate if (softsp->bto_ctr++ >= bto_cnt)
785*0Sstevel@tonic-gate return (1);
786*0Sstevel@tonic-gate return (0);
787*0Sstevel@tonic-gate }
788*0Sstevel@tonic-gate
789*0Sstevel@tonic-gate static uint_t
sbus_ctrl_ecc_err(struct sbus_soft_state * softsp)790*0Sstevel@tonic-gate sbus_ctrl_ecc_err(struct sbus_soft_state *softsp)
791*0Sstevel@tonic-gate {
792*0Sstevel@tonic-gate uint64_t t_sb_csr;
793*0Sstevel@tonic-gate ushort_t id, inst;
794*0Sstevel@tonic-gate
795*0Sstevel@tonic-gate t_sb_csr = *softsp->sbus_ctrl_reg;
796*0Sstevel@tonic-gate id = (ushort_t)softsp->upa_id;
797*0Sstevel@tonic-gate inst = (ushort_t)ddi_get_instance(softsp->dip);
798*0Sstevel@tonic-gate
799*0Sstevel@tonic-gate if (debug_sysio_errs) {
800*0Sstevel@tonic-gate cmn_err(CE_CONT, "sbus_ctrl_ecc_error: SBus%d Control Reg "
801*0Sstevel@tonic-gate "0x%016llx Id %d\n", inst, (u_longlong_t)t_sb_csr, id);
802*0Sstevel@tonic-gate }
803*0Sstevel@tonic-gate
804*0Sstevel@tonic-gate if (t_sb_csr & (SB_CSR_DPERR_S14|SB_CSR_DPERR_S13|SB_CSR_DPERR_S3|
805*0Sstevel@tonic-gate SB_CSR_DPERR_S2|SB_CSR_DPERR_S1|SB_CSR_DPERR_S0|SB_CSR_PIO_PERRS)) {
806*0Sstevel@tonic-gate struct async_flt aflt;
807*0Sstevel@tonic-gate
808*0Sstevel@tonic-gate *softsp->sbus_ctrl_reg = t_sb_csr; /* clear error bits */
809*0Sstevel@tonic-gate
810*0Sstevel@tonic-gate bzero(&aflt, sizeof (aflt));
811*0Sstevel@tonic-gate aflt.flt_id = gethrtime();
812*0Sstevel@tonic-gate aflt.flt_stat = t_sb_csr;
813*0Sstevel@tonic-gate aflt.flt_func = sbus_log_csr_error;
814*0Sstevel@tonic-gate aflt.flt_bus_id = id;
815*0Sstevel@tonic-gate aflt.flt_inst = inst;
816*0Sstevel@tonic-gate aflt.flt_status = ECC_IOBUS;
817*0Sstevel@tonic-gate aflt.flt_class = BUS_FAULT;
818*0Sstevel@tonic-gate aflt.flt_panic = 1;
819*0Sstevel@tonic-gate
820*0Sstevel@tonic-gate errorq_dispatch(ue_queue, &aflt, sizeof (aflt), aflt.flt_panic);
821*0Sstevel@tonic-gate return (BF_FATAL);
822*0Sstevel@tonic-gate }
823*0Sstevel@tonic-gate
824*0Sstevel@tonic-gate return (BF_NONE);
825*0Sstevel@tonic-gate }
826*0Sstevel@tonic-gate
827*0Sstevel@tonic-gate /*ARGSUSED*/
828*0Sstevel@tonic-gate static void
sbus_log_csr_error(struct async_flt * aflt,char * unum)829*0Sstevel@tonic-gate sbus_log_csr_error(struct async_flt *aflt, char *unum)
830*0Sstevel@tonic-gate {
831*0Sstevel@tonic-gate uint64_t t_sb_csr = aflt->flt_stat;
832*0Sstevel@tonic-gate uint_t id = aflt->flt_bus_id;
833*0Sstevel@tonic-gate uint_t inst = aflt->flt_inst;
834*0Sstevel@tonic-gate
835*0Sstevel@tonic-gate /*
836*0Sstevel@tonic-gate * Print out SBus error information.
837*0Sstevel@tonic-gate */
838*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_DPERR_S14) {
839*0Sstevel@tonic-gate cmn_err(CE_WARN,
840*0Sstevel@tonic-gate "SBus%d Slot 14 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
841*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
842*0Sstevel@tonic-gate }
843*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_DPERR_S13) {
844*0Sstevel@tonic-gate cmn_err(CE_WARN,
845*0Sstevel@tonic-gate "SBus%d Slot 13 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
846*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
847*0Sstevel@tonic-gate }
848*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_DPERR_S3) {
849*0Sstevel@tonic-gate cmn_err(CE_WARN,
850*0Sstevel@tonic-gate "SBus%d Slot 3 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
851*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
852*0Sstevel@tonic-gate }
853*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_DPERR_S2) {
854*0Sstevel@tonic-gate cmn_err(CE_WARN,
855*0Sstevel@tonic-gate "SBus%d Slot 2 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
856*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
857*0Sstevel@tonic-gate }
858*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_DPERR_S1) {
859*0Sstevel@tonic-gate cmn_err(CE_WARN,
860*0Sstevel@tonic-gate "SBus%d Slot 1 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
861*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
862*0Sstevel@tonic-gate }
863*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_DPERR_S0) {
864*0Sstevel@tonic-gate cmn_err(CE_WARN,
865*0Sstevel@tonic-gate "SBus%d Slot 0 DVMA Parity Error: AFSR 0x%08x.%08x Id %d",
866*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
867*0Sstevel@tonic-gate }
868*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_PPERR_S15) {
869*0Sstevel@tonic-gate cmn_err(CE_WARN,
870*0Sstevel@tonic-gate "SBus%d Slot 15 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
871*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
872*0Sstevel@tonic-gate }
873*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_PPERR_S14) {
874*0Sstevel@tonic-gate cmn_err(CE_WARN,
875*0Sstevel@tonic-gate "SBus%d Slot 14 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
876*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
877*0Sstevel@tonic-gate }
878*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_PPERR_S13) {
879*0Sstevel@tonic-gate cmn_err(CE_WARN,
880*0Sstevel@tonic-gate "SBus%d Slot 13 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
881*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
882*0Sstevel@tonic-gate }
883*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_PPERR_S3) {
884*0Sstevel@tonic-gate cmn_err(CE_WARN,
885*0Sstevel@tonic-gate "SBus%d Slot 3 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
886*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
887*0Sstevel@tonic-gate }
888*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_PPERR_S2) {
889*0Sstevel@tonic-gate cmn_err(CE_WARN,
890*0Sstevel@tonic-gate "SBus%d Slot 2 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
891*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
892*0Sstevel@tonic-gate }
893*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_PPERR_S1) {
894*0Sstevel@tonic-gate cmn_err(CE_WARN,
895*0Sstevel@tonic-gate "SBus%d Slot 1 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
896*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
897*0Sstevel@tonic-gate }
898*0Sstevel@tonic-gate if (t_sb_csr & SB_CSR_PPERR_S0) {
899*0Sstevel@tonic-gate cmn_err(CE_WARN,
900*0Sstevel@tonic-gate "SBus%d Slot 0 PIO Parity Error: AFSR 0x%08x.%08x Id %d",
901*0Sstevel@tonic-gate inst, (uint32_t)(t_sb_csr>>32), (uint32_t)t_sb_csr, id);
902*0Sstevel@tonic-gate }
903*0Sstevel@tonic-gate }
904*0Sstevel@tonic-gate
905*0Sstevel@tonic-gate /*
906*0Sstevel@tonic-gate * Sysio Thermal Warning interrupt handler
907*0Sstevel@tonic-gate */
908*0Sstevel@tonic-gate static uint_t
sysio_thermal_warn_intr(struct sbus_soft_state * softsp)909*0Sstevel@tonic-gate sysio_thermal_warn_intr(struct sbus_soft_state *softsp)
910*0Sstevel@tonic-gate {
911*0Sstevel@tonic-gate volatile uint64_t *clear_reg;
912*0Sstevel@tonic-gate volatile uint64_t tmp_mondo_vec;
913*0Sstevel@tonic-gate volatile uint64_t *mondo_vec_reg;
914*0Sstevel@tonic-gate const char thermal_warn_msg[] =
915*0Sstevel@tonic-gate "Severe over-temperature condition detected!";
916*0Sstevel@tonic-gate
917*0Sstevel@tonic-gate /*
918*0Sstevel@tonic-gate * Take off the Thermal Warning interrupt and
919*0Sstevel@tonic-gate * remove its interrupt handler.
920*0Sstevel@tonic-gate */
921*0Sstevel@tonic-gate mondo_vec_reg = (softsp->intr_mapping_reg + THERMAL_MAPREG);
922*0Sstevel@tonic-gate tmp_mondo_vec = *mondo_vec_reg;
923*0Sstevel@tonic-gate tmp_mondo_vec &= ~INTERRUPT_VALID;
924*0Sstevel@tonic-gate *mondo_vec_reg = tmp_mondo_vec;
925*0Sstevel@tonic-gate
926*0Sstevel@tonic-gate ddi_remove_intr(softsp->dip, 4, NULL);
927*0Sstevel@tonic-gate
928*0Sstevel@tonic-gate clear_reg = (softsp->clr_intr_reg + THERMAL_CLEAR);
929*0Sstevel@tonic-gate *clear_reg = 0;
930*0Sstevel@tonic-gate
931*0Sstevel@tonic-gate if (oven_test) {
932*0Sstevel@tonic-gate cmn_err(CE_NOTE, "OVEN TEST: %s", thermal_warn_msg);
933*0Sstevel@tonic-gate return (DDI_INTR_CLAIMED);
934*0Sstevel@tonic-gate }
935*0Sstevel@tonic-gate
936*0Sstevel@tonic-gate cmn_err(CE_WARN, "%s", thermal_warn_msg);
937*0Sstevel@tonic-gate cmn_err(CE_WARN, "Powering down...");
938*0Sstevel@tonic-gate
939*0Sstevel@tonic-gate do_shutdown();
940*0Sstevel@tonic-gate
941*0Sstevel@tonic-gate /*
942*0Sstevel@tonic-gate * just in case do_shutdown() fails
943*0Sstevel@tonic-gate */
944*0Sstevel@tonic-gate (void) timeout((void(*)(void *))power_down, NULL,
945*0Sstevel@tonic-gate thermal_powerdown_delay * hz);
946*0Sstevel@tonic-gate
947*0Sstevel@tonic-gate return (DDI_INTR_CLAIMED);
948*0Sstevel@tonic-gate }
949