1 /***********************license start***************
2 * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Networks nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * This Software, including technical data, may be subject to U.S. export control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
44 * Prototypes for custom error handler function not handled by the default
45 * message display error function.
47 * <hr>$Revision: 44252 $<hr>
49 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
50 #include <asm/octeon/cvmx.h>
51 #include <asm/octeon/cvmx-error.h>
52 #include <asm/octeon/cvmx-error-custom.h>
53 #include <asm/octeon/cvmx-helper.h>
54 #include <asm/octeon/cvmx-l2c.h>
55 #include <asm/octeon/cvmx-pcie.h>
56 #include <asm/octeon/cvmx-pexp-defs.h>
57 #include <asm/octeon/cvmx-dfa-defs.h>
58 #include <asm/octeon/cvmx-gmxx-defs.h>
59 #include <asm/octeon/cvmx-lmcx-defs.h>
60 #include <asm/octeon/cvmx-pemx-defs.h>
61 #define PRINT_ERROR(format, ...) cvmx_safe_printf("ERROR " format, ##__VA_ARGS__)
64 #include "cvmx-error.h"
65 #include "cvmx-error-custom.h"
66 #include "cvmx-helper.h"
68 #include "cvmx-pcie.h"
69 #include "cvmx-interrupt.h"
74 * XAUI interfaces need to be reset whenever a local or remote fault
75 * is detected. Calling autoconf takes the link through a reset.
81 static int __cvmx_error_handle_gmxx_rxx_int_reg(const struct cvmx_error_info *info)
83 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
84 int ipd_port = info->group_index;
85 cvmx_helper_link_autoconf(ipd_port);
87 cvmx_write_csr(info->status_addr, info->status_mask);
93 * When NPEI_INT_SUM[C0_LDWN] is set, the PCIe block requires a shutdown and
94 * initialization to bring the link back up. This handler does this for port 0.
95 * Note that config space is not enumerated again, so the devices will still be
102 static int __cvmx_error_handle_npei_int_sum_c0_ldwn(const struct cvmx_error_info *info)
104 cvmx_ciu_soft_prst_t ciu_soft_prst;
105 PRINT_ERROR("NPEI_INT_SUM[C0_LDWN]: Reset request due to link0 down status.\n");
106 ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
107 if (!ciu_soft_prst.s.soft_prst)
109 /* Attempt to automatically bring the link back up */
110 cvmx_pcie_rc_shutdown(0);
111 cvmx_pcie_rc_initialize(0);
113 cvmx_write_csr(CVMX_PEXP_NPEI_INT_SUM, cvmx_read_csr(CVMX_PEXP_NPEI_INT_SUM));
119 * When NPEI_INT_SUM[C1_LDWN] is set, the PCIe block requires a shutdown and
120 * initialization to bring the link back up. This handler does this for port 1.
121 * Note that config space is not enumerated again, so the devices will still be
128 static int __cvmx_error_handle_npei_int_sum_c1_ldwn(const struct cvmx_error_info *info)
130 cvmx_ciu_soft_prst_t ciu_soft_prst;
131 PRINT_ERROR("NPEI_INT_SUM[C1_LDWN]: Reset request due to link1 down status.\n");
132 ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
133 if (!ciu_soft_prst.s.soft_prst)
135 /* Attempt to automatically bring the link back up */
136 cvmx_pcie_rc_shutdown(1);
137 cvmx_pcie_rc_initialize(1);
139 cvmx_write_csr(CVMX_PEXP_NPEI_INT_SUM, cvmx_read_csr(CVMX_PEXP_NPEI_INT_SUM));
145 * Some errors require more complicated error handing functions than the
146 * automatically generated functions in cvmx-error-init-*.c. This function
147 * replaces these handers with hand coded functions for these special cases.
149 * @return Zero on success, negative on failure.
151 int __cvmx_error_custom_initialize(void)
153 if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
155 cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
156 CVMX_GMXX_RXX_INT_REG(0,0), 1ull<<21 /* rem_fault */,
157 __cvmx_error_handle_gmxx_rxx_int_reg, 0, NULL, NULL);
158 cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
159 CVMX_GMXX_RXX_INT_REG(0,0), 1ull<<20 /* loc_fault */,
160 __cvmx_error_handle_gmxx_rxx_int_reg, 0, NULL, NULL);
162 if (OCTEON_IS_MODEL(OCTEON_CN56XX))
164 cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
165 CVMX_GMXX_RXX_INT_REG(0,1), 1ull<<21 /* rem_fault */,
166 __cvmx_error_handle_gmxx_rxx_int_reg, 0, NULL, NULL);
167 cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
168 CVMX_GMXX_RXX_INT_REG(0,1), 1ull<<20 /* loc_fault */,
169 __cvmx_error_handle_gmxx_rxx_int_reg, 0, NULL, NULL);
171 if (octeon_has_feature(OCTEON_FEATURE_NPEI))
173 cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
174 CVMX_PEXP_NPEI_INT_SUM, 1ull<<59 /* c0_ldwn */,
175 __cvmx_error_handle_npei_int_sum_c0_ldwn, 0, NULL, NULL);
176 cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
177 CVMX_PEXP_NPEI_INT_SUM, 1ull<<60 /* c1_ldwn */,
178 __cvmx_error_handle_npei_int_sum_c1_ldwn, 0, NULL, NULL);
181 /* CN63XX pass 1.x has a bug where the PCIe config CRS counter does not
182 stop. Disable reporting errors from CRS */
183 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
185 cvmx_error_disable(CVMX_ERROR_REGISTER_IO64, CVMX_PEMX_INT_SUM(0),
187 cvmx_error_disable(CVMX_ERROR_REGISTER_IO64, CVMX_PEMX_INT_SUM(0),
189 cvmx_error_disable(CVMX_ERROR_REGISTER_IO64, CVMX_PEMX_INT_SUM(1),
191 cvmx_error_disable(CVMX_ERROR_REGISTER_IO64, CVMX_PEMX_INT_SUM(1),
199 * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
200 * special handling instead of the normal __cvmx_error_display() function.
206 int __cvmx_error_handle_dfa_err_cp2dbe(const struct cvmx_error_info *info)
208 cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
209 PRINT_ERROR("DFA_ERR[CP2DBE]: DFA PP-CP2 Double Bit Error Detected\n");
215 * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
216 * special handling instead of the normal __cvmx_error_display() function.
222 int __cvmx_error_handle_dfa_err_cp2perr(const struct cvmx_error_info *info)
224 cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
225 PRINT_ERROR("DFA_ERR[CP2PERR]: PP-CP2 Parity Error Detected\n");
231 * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
232 * special handling instead of the normal __cvmx_error_display() function.
238 int __cvmx_error_handle_dfa_err_cp2sbe(const struct cvmx_error_info *info)
240 cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
241 PRINT_ERROR("DFA_ERR[CP2SBE]: DFA PP-CP2 Single Bit Error Corrected\n");
247 * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
248 * special handling instead of the normal __cvmx_error_display() function.
254 int __cvmx_error_handle_dfa_err_dblovf(const struct cvmx_error_info *info)
256 cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
257 PRINT_ERROR("DFA_ERR[DBLOVF]: Doorbell Overflow detected\n");
263 * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
264 * special handling instead of the normal __cvmx_error_display() function.
270 int __cvmx_error_handle_dfa_err_dtedbe(const struct cvmx_error_info *info)
272 cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
273 PRINT_ERROR("DFA_ERR[DTEDBE]: DFA DTE 29b Double Bit Error Detected\n");
279 * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
280 * special handling instead of the normal __cvmx_error_display() function.
286 int __cvmx_error_handle_dfa_err_dteperr(const struct cvmx_error_info *info)
288 cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
289 PRINT_ERROR("DFA_ERR[DTEPERR]: DTE Parity Error Detected\n");
295 * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
296 * special handling instead of the normal __cvmx_error_display() function.
302 int __cvmx_error_handle_dfa_err_dtesbe(const struct cvmx_error_info *info)
304 cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
305 PRINT_ERROR("DFA_ERR[DTESBE]: DFA DTE 29b Single Bit Error Corrected\n");
311 * L2D_ERR contains R/W1C bits along with R/W bits. This means that it requires
312 * special handling instead of the normal __cvmx_error_display() function.
318 int __cvmx_error_handle_l2d_err_ded_err(const struct cvmx_error_info *info)
321 cvmx_l2d_fadr_t fadr;
322 uint64_t syn0 = cvmx_read_csr(CVMX_L2D_FSYN0);
323 uint64_t syn1 = cvmx_read_csr(CVMX_L2D_FSYN1);
324 derr.u64 = cvmx_read_csr(CVMX_L2D_ERR);
325 fadr.u64 = cvmx_read_csr(CVMX_L2D_FADR);
327 PRINT_ERROR("L2D_ERR[DED_ERR] ECC double: fadr: 0x%llx, syn0:0x%llx, syn1: 0x%llx\n",
328 (unsigned long long)fadr.u64, (unsigned long long)syn0, (unsigned long long)syn1);
329 /* Flush the line that had the error */
330 cvmx_l2c_flush_line(fadr.s.fset, fadr.s.fadr >> 1);
331 cvmx_write_csr(CVMX_L2D_ERR, derr.u64);
337 * L2D_ERR contains R/W1C bits along with R/W bits. This means that it requires
338 * special handling instead of the normal __cvmx_error_display() function.
344 int __cvmx_error_handle_l2d_err_sec_err(const struct cvmx_error_info *info)
347 cvmx_l2d_fadr_t fadr;
348 uint64_t syn0 = cvmx_read_csr(CVMX_L2D_FSYN0);
349 uint64_t syn1 = cvmx_read_csr(CVMX_L2D_FSYN1);
350 derr.u64 = cvmx_read_csr(CVMX_L2D_ERR);
351 fadr.u64 = cvmx_read_csr(CVMX_L2D_FADR);
353 PRINT_ERROR("L2D_ERR[SEC_ERR] ECC single: fadr: 0x%llx, syn0:0x%llx, syn1: 0x%llx\n",
354 (unsigned long long)fadr.u64, (unsigned long long)syn0, (unsigned long long)syn1);
355 /* Flush the line that had the error */
356 cvmx_l2c_flush_line(fadr.s.fset, fadr.s.fadr >> 1);
357 cvmx_write_csr(CVMX_L2D_ERR, derr.u64);
363 * L2T_ERR contains R/W1C bits along with R/W bits. This means that it requires
364 * special handling instead of the normal __cvmx_error_display() function.
370 int __cvmx_error_handle_l2t_err_ded_err(const struct cvmx_error_info *info)
373 terr.u64 = cvmx_read_csr(CVMX_L2T_ERR);
374 cvmx_write_csr(CVMX_L2T_ERR, terr.u64);
375 PRINT_ERROR("L2T_ERR[DED_ERR]: double bit:\tfadr: 0x%x, fset: 0x%x, fsyn: 0x%x\n",
376 terr.s.fadr, terr.s.fset, terr.s.fsyn);
379 /* Syndrome is zero, which means error was in non-hit line,
380 so flush all associations */
382 int l2_assoc = cvmx_l2c_get_num_assoc();
384 for (i = 0; i < l2_assoc; i++)
385 cvmx_l2c_flush_line(i, terr.s.fadr);
388 cvmx_l2c_flush_line(terr.s.fset, terr.s.fadr);
394 * L2T_ERR contains R/W1C bits along with R/W bits. This means that it requires
395 * special handling instead of the normal __cvmx_error_display() function.
401 int __cvmx_error_handle_l2t_err_lckerr2(const struct cvmx_error_info *info)
403 cvmx_write_csr(CVMX_L2T_ERR, cvmx_read_csr(CVMX_L2T_ERR));
404 PRINT_ERROR("L2T_ERR[LCKERR2]: HW detected a case where a Rd/Wr Miss from PP#n could not find an available/unlocked set (for replacement).\n");
410 * L2T_ERR contains R/W1C bits along with R/W bits. This means that it requires
411 * special handling instead of the normal __cvmx_error_display() function.
417 int __cvmx_error_handle_l2t_err_lckerr(const struct cvmx_error_info *info)
419 cvmx_write_csr(CVMX_L2T_ERR, cvmx_read_csr(CVMX_L2T_ERR));
420 PRINT_ERROR("L2T_ERR[LCKERR]: SW attempted to LOCK DOWN the last available set of the INDEX (which is ignored by HW - but reported to SW).\n");
426 * L2T_ERR contains R/W1C bits along with R/W bits. This means that it requires
427 * special handling instead of the normal __cvmx_error_display() function.
433 int __cvmx_error_handle_l2t_err_sec_err(const struct cvmx_error_info *info)
436 terr.u64 = cvmx_read_csr(CVMX_L2T_ERR);
437 cvmx_write_csr(CVMX_L2T_ERR, terr.u64);
438 PRINT_ERROR("L2T_ERR[SEC_ERR]: single bit:\tfadr: 0x%x, fset: 0x%x, fsyn: 0x%x\n",
439 terr.s.fadr, terr.s.fset, terr.s.fsyn);
442 /* Syndrome is zero, which means error was in non-hit line,
443 so flush all associations */
445 int l2_assoc = cvmx_l2c_get_num_assoc();
447 for (i = 0; i < l2_assoc; i++)
448 cvmx_l2c_flush_line(i, terr.s.fadr);
451 cvmx_l2c_flush_line(terr.s.fset, terr.s.fadr);
458 * LMCX_MEM_CFG0 contains R/W1C bits along with R/W bits. This means that it
459 * requires special handling instead of the normal __cvmx_error_display()
466 static int __cvmx_error_handle_lmcx_mem_cfg0(const struct cvmx_error_info *info)
468 int ddr_controller = info->group_index;
469 cvmx_lmcx_mem_cfg0_t mem_cfg0;
470 cvmx_lmcx_fadr_t fadr;
474 mem_cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(ddr_controller));
475 fadr.u64 = cvmx_read_csr(CVMX_LMCX_FADR(ddr_controller));
476 cvmx_write_csr(CVMX_LMCX_MEM_CFG0(ddr_controller),mem_cfg0.u64);
478 sec_err = cvmx_dpop(mem_cfg0.s.sec_err);
479 ded_err = cvmx_dpop(mem_cfg0.s.ded_err);
481 if (ded_err || sec_err)
483 PRINT_ERROR("DDR%d ECC: %d Single bit corrections, %d Double bit errors\n"
484 "DDR%d ECC:\tFailing dimm: %u\n"
485 "DDR%d ECC:\tFailing rank: %u\n"
486 "DDR%d ECC:\tFailing bank: %u\n"
487 "DDR%d ECC:\tFailing row: 0x%x\n"
488 "DDR%d ECC:\tFailing column: 0x%x\n",
489 ddr_controller, sec_err, ded_err,
490 ddr_controller, fadr.cn38xx.fdimm,
491 ddr_controller, fadr.cn38xx.fbunk,
492 ddr_controller, fadr.cn38xx.fbank,
493 ddr_controller, fadr.cn38xx.frow,
494 ddr_controller, fadr.cn38xx.fcol);
501 * LMCX_MEM_CFG0 contains R/W1C bits along with R/W bits. This means that it
502 * requires special handling instead of the normal __cvmx_error_display()
509 int __cvmx_error_handle_lmcx_mem_cfg0_ded_err(const struct cvmx_error_info *info)
511 return __cvmx_error_handle_lmcx_mem_cfg0(info);
516 * LMCX_MEM_CFG0 contains R/W1C bits along with R/W bits. This means that it
517 * requires special handling instead of the normal __cvmx_error_display()
524 int __cvmx_error_handle_lmcx_mem_cfg0_sec_err(const struct cvmx_error_info *info)
526 return __cvmx_error_handle_lmcx_mem_cfg0(info);
531 * POW_ECC_ERR contains R/W1C bits along with R/W bits. This means that it
532 * requires special handling instead of the normal __cvmx_error_display()
539 int __cvmx_error_handle_pow_ecc_err_dbe(const struct cvmx_error_info *info)
541 cvmx_write_csr(CVMX_POW_ECC_ERR, cvmx_read_csr(CVMX_POW_ECC_ERR));
542 PRINT_ERROR("POW_ECC_ERR[DBE]: POW double bit error\n");
548 * POW_ECC_ERR contains R/W1C bits along with R/W bits. This means that it
549 * requires special handling instead of the normal __cvmx_error_display()
556 int __cvmx_error_handle_pow_ecc_err_iop(const struct cvmx_error_info *info)
558 cvmx_pow_ecc_err_t err;
559 err.u64 = cvmx_read_csr(CVMX_POW_ECC_ERR);
560 cvmx_write_csr(CVMX_POW_ECC_ERR, err.u64);
561 if (err.s.iop & (1 << 0))
562 PRINT_ERROR("POW_ECC_ERR[IOP0]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/DESCH/UPD_WQP from PP in NULL_NULL state\n");
563 if (err.s.iop & (1 << 1))
564 PRINT_ERROR("POW_ECC_ERR[IOP1]: Received SWTAG/SWTAG_DESCH/DESCH/UPD_WQP from PP in NULL state\n");
565 if (err.s.iop & (1 << 2))
566 PRINT_ERROR("POW_ECC_ERR[IOP2]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/GET_WORK from PP with pending tag switch to ORDERED or ATOMIC\n");
567 if (err.s.iop & (1 << 3))
568 PRINT_ERROR("POW_ECC_ERR[IOP3]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH from PP with tag specified as NULL_NULL\n");
569 if (err.s.iop & (1 << 4))
570 PRINT_ERROR("POW_ECC_ERR[IOP4]: Received SWTAG_FULL/SWTAG_DESCH from PP with tag specified as NULL\n");
571 if (err.s.iop & (1 << 5))
572 PRINT_ERROR("POW_ECC_ERR[IOP5]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/DESCH/UPD_WQP/GET_WORK/NULL_RD from PP with GET_WORK pending\n");
573 if (err.s.iop & (1 << 6))
574 PRINT_ERROR("POW_ECC_ERR[IOP6]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/DESCH/UPD_WQP/GET_WORK/NULL_RD from PP with NULL_RD pending\n");
575 if (err.s.iop & (1 << 7))
576 PRINT_ERROR("POW_ECC_ERR[IOP7]: Received CLR_NSCHED from PP with SWTAG_DESCH/DESCH/CLR_NSCHED pending\n");
577 if (err.s.iop & (1 << 8))
578 PRINT_ERROR("POW_ECC_ERR[IOP8]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/DESCH/UPD_WQP/GET_WORK/NULL_RD from PP with CLR_NSCHED pending\n");
579 if (err.s.iop & (1 << 9))
580 PRINT_ERROR("POW_ECC_ERR[IOP9]: Received illegal opcode\n");
581 if (err.s.iop & (1 << 10))
582 PRINT_ERROR("POW_ECC_ERR[IOP10]: Received ADD_WORK with tag specified as NULL_NULL\n");
583 if (err.s.iop & (1 << 11))
584 PRINT_ERROR("POW_ECC_ERR[IOP11]: Received DBG load from PP with DBG load pending\n");
585 if (err.s.iop & (1 << 12))
586 PRINT_ERROR("POW_ECC_ERR[IOP12]: Received CSR load from PP with CSR load pending\n");
592 * POW_ECC_ERR contains R/W1C bits along with R/W bits. This means that it
593 * requires special handling instead of the normal __cvmx_error_display()
600 int __cvmx_error_handle_pow_ecc_err_rpe(const struct cvmx_error_info *info)
602 cvmx_write_csr(CVMX_POW_ECC_ERR, cvmx_read_csr(CVMX_POW_ECC_ERR));
603 PRINT_ERROR("POW_ECC_ERR[RPE]: Remote pointer error\n");
609 * POW_ECC_ERR contains R/W1C bits along with R/W bits. This means that it
610 * requires special handling instead of the normal __cvmx_error_display()
617 int __cvmx_error_handle_pow_ecc_err_sbe(const struct cvmx_error_info *info)
619 cvmx_write_csr(CVMX_POW_ECC_ERR, cvmx_read_csr(CVMX_POW_ECC_ERR));
620 PRINT_ERROR("POW_ECC_ERR[SBE]: POW single bit error\n");