|
@@ -460,3 +460,154 @@ mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
|
|
frame->exc_addr);
|
|
frame->exc_addr);
|
|
printk(" Summary of arithmetic traps = %16lx\n",
|
|
printk(" Summary of arithmetic traps = %16lx\n",
|
|
frame->exc_sum);
|
|
frame->exc_sum);
|
|
|
|
+ printk(" Exception mask = %16lx\n",
|
|
|
|
+ frame->exc_mask);
|
|
|
|
+ printk(" Base address for PALcode = %16lx\n",
|
|
|
|
+ frame->pal_base);
|
|
|
|
+ printk(" Interrupt Status Reg = %16lx\n",
|
|
|
|
+ frame->isr);
|
|
|
|
+ printk(" CURRENT SETUP OF EV5 IBOX = %16lx\n",
|
|
|
|
+ frame->icsr);
|
|
|
|
+ printk(" I-CACHE Reg %s parity error = %16lx\n",
|
|
|
|
+ (frame->ic_perr_stat & 0x800L) ?
|
|
|
|
+ "Data" : "Tag",
|
|
|
|
+ frame->ic_perr_stat);
|
|
|
|
+ printk(" D-CACHE error Reg = %16lx\n",
|
|
|
|
+ frame->dc_perr_stat);
|
|
|
|
+ if (frame->dc_perr_stat & 0x2) {
|
|
|
|
+ switch (frame->dc_perr_stat & 0x03c) {
|
|
|
|
+ case 8:
|
|
|
|
+ printk(" Data error in bank 1\n");
|
|
|
|
+ break;
|
|
|
|
+ case 4:
|
|
|
|
+ printk(" Data error in bank 0\n");
|
|
|
|
+ break;
|
|
|
|
+ case 20:
|
|
|
|
+ printk(" Tag error in bank 1\n");
|
|
|
|
+ break;
|
|
|
|
+ case 10:
|
|
|
|
+ printk(" Tag error in bank 0\n");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ printk(" Effective VA = %16lx\n",
|
|
|
|
+ frame->va);
|
|
|
|
+ printk(" Reason for D-stream = %16lx\n",
|
|
|
|
+ frame->mm_stat);
|
|
|
|
+ printk(" EV5 SCache address = %16lx\n",
|
|
|
|
+ frame->sc_addr);
|
|
|
|
+ printk(" EV5 SCache TAG/Data parity = %16lx\n",
|
|
|
|
+ frame->sc_stat);
|
|
|
|
+ printk(" EV5 BC_TAG_ADDR = %16lx\n",
|
|
|
|
+ frame->bc_tag_addr);
|
|
|
|
+ printk(" EV5 EI_ADDR: Phys addr of Xfer = %16lx\n",
|
|
|
|
+ frame->ei_addr);
|
|
|
|
+ printk(" Fill Syndrome = %16lx\n",
|
|
|
|
+ frame->fill_syndrome);
|
|
|
|
+ printk(" EI_STAT reg = %16lx\n",
|
|
|
|
+ frame->ei_stat);
|
|
|
|
+ printk(" LD_LOCK = %16lx\n",
|
|
|
|
+ frame->ld_lock);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+mcpcia_print_system_area(unsigned long la_ptr)
|
|
|
|
+{
|
|
|
|
+ struct el_common *frame;
|
|
|
|
+ struct pci_controller *hose;
|
|
|
|
+
|
|
|
|
+ struct IOD_subpacket {
|
|
|
|
+ unsigned long base;
|
|
|
|
+ unsigned int whoami;
|
|
|
|
+ unsigned int rsvd1;
|
|
|
|
+ unsigned int pci_rev;
|
|
|
|
+ unsigned int cap_ctrl;
|
|
|
|
+ unsigned int hae_mem;
|
|
|
|
+ unsigned int hae_io;
|
|
|
|
+ unsigned int int_ctl;
|
|
|
|
+ unsigned int int_reg;
|
|
|
|
+ unsigned int int_mask0;
|
|
|
|
+ unsigned int int_mask1;
|
|
|
|
+ unsigned int mc_err0;
|
|
|
|
+ unsigned int mc_err1;
|
|
|
|
+ unsigned int cap_err;
|
|
|
|
+ unsigned int rsvd2;
|
|
|
|
+ unsigned int pci_err1;
|
|
|
|
+ unsigned int mdpa_stat;
|
|
|
|
+ unsigned int mdpa_syn;
|
|
|
|
+ unsigned int mdpb_stat;
|
|
|
|
+ unsigned int mdpb_syn;
|
|
|
|
+ unsigned int rsvd3;
|
|
|
|
+ unsigned int rsvd4;
|
|
|
|
+ unsigned int rsvd5;
|
|
|
|
+ } *iodpp;
|
|
|
|
+
|
|
|
|
+ frame = (struct el_common *)la_ptr;
|
|
|
|
+ iodpp = (struct IOD_subpacket *) (la_ptr + frame->sys_offset);
|
|
|
|
+
|
|
|
|
+ for (hose = hose_head; hose; hose = hose->next, iodpp++) {
|
|
|
|
+
|
|
|
|
+ printk("IOD %d Register Subpacket - Bridge Base Address %16lx\n",
|
|
|
|
+ hose->index, iodpp->base);
|
|
|
|
+ printk(" WHOAMI = %8x\n", iodpp->whoami);
|
|
|
|
+ printk(" PCI_REV = %8x\n", iodpp->pci_rev);
|
|
|
|
+ printk(" CAP_CTRL = %8x\n", iodpp->cap_ctrl);
|
|
|
|
+ printk(" HAE_MEM = %8x\n", iodpp->hae_mem);
|
|
|
|
+ printk(" HAE_IO = %8x\n", iodpp->hae_io);
|
|
|
|
+ printk(" INT_CTL = %8x\n", iodpp->int_ctl);
|
|
|
|
+ printk(" INT_REG = %8x\n", iodpp->int_reg);
|
|
|
|
+ printk(" INT_MASK0 = %8x\n", iodpp->int_mask0);
|
|
|
|
+ printk(" INT_MASK1 = %8x\n", iodpp->int_mask1);
|
|
|
|
+ printk(" MC_ERR0 = %8x\n", iodpp->mc_err0);
|
|
|
|
+ printk(" MC_ERR1 = %8x\n", iodpp->mc_err1);
|
|
|
|
+ printk(" CAP_ERR = %8x\n", iodpp->cap_err);
|
|
|
|
+ printk(" PCI_ERR1 = %8x\n", iodpp->pci_err1);
|
|
|
|
+ printk(" MDPA_STAT = %8x\n", iodpp->mdpa_stat);
|
|
|
|
+ printk(" MDPA_SYN = %8x\n", iodpp->mdpa_syn);
|
|
|
|
+ printk(" MDPB_STAT = %8x\n", iodpp->mdpb_stat);
|
|
|
|
+ printk(" MDPB_SYN = %8x\n", iodpp->mdpb_syn);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+mcpcia_machine_check(unsigned long vector, unsigned long la_ptr)
|
|
|
|
+{
|
|
|
|
+ struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
|
|
|
|
+ unsigned int cpu = smp_processor_id();
|
|
|
|
+ int expected;
|
|
|
|
+
|
|
|
|
+ mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
|
|
|
|
+ expected = mcheck_expected(cpu);
|
|
|
|
+
|
|
|
|
+ mb();
|
|
|
|
+ mb(); /* magic */
|
|
|
|
+ draina();
|
|
|
|
+
|
|
|
|
+ switch (expected) {
|
|
|
|
+ case 0:
|
|
|
|
+ {
|
|
|
|
+ /* FIXME: how do we figure out which hose the
|
|
|
|
+ error was on? */
|
|
|
|
+ struct pci_controller *hose;
|
|
|
|
+ for (hose = hose_head; hose; hose = hose->next)
|
|
|
|
+ mcpcia_pci_clr_err(MCPCIA_HOSE2MID(hose->index));
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case 1:
|
|
|
|
+ mcpcia_pci_clr_err(mcheck_extra(cpu));
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ /* Otherwise, we're being called from mcpcia_probe_hose
|
|
|
|
+ and there's no hose clear an error from. */
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ wrmces(0x7);
|
|
|
|
+ mb();
|
|
|
|
+
|
|
|
|
+ process_mcheck_info(vector, la_ptr, "MCPCIA", expected != 0);
|
|
|
|
+ if (!expected && vector != 0x620 && vector != 0x630) {
|
|
|
|
+ mcpcia_print_uncorrectable(mchk_logout);
|
|
|
|
+ mcpcia_print_system_area(la_ptr);
|
|
|
|
+ }
|
|
|
|
+}
|