|
@@ -826,3 +826,187 @@ cia_pci_clr_err(void)
|
|
|
*(vip)CIA_IOC_CIA_ERR = jd;
|
|
|
mb();
|
|
|
*(vip)CIA_IOC_CIA_ERR; /* re-read to force write. */
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_VERBOSE_MCHECK
|
|
|
+static void
|
|
|
+cia_decode_pci_error(struct el_CIA_sysdata_mcheck *cia, const char *msg)
|
|
|
+{
|
|
|
+ static const char * const pci_cmd_desc[16] = {
|
|
|
+ "Interrupt Acknowledge", "Special Cycle", "I/O Read",
|
|
|
+ "I/O Write", "Reserved 0x4", "Reserved 0x5", "Memory Read",
|
|
|
+ "Memory Write", "Reserved 0x8", "Reserved 0x9",
|
|
|
+ "Configuration Read", "Configuration Write",
|
|
|
+ "Memory Read Multiple", "Dual Address Cycle",
|
|
|
+ "Memory Read Line", "Memory Write and Invalidate"
|
|
|
+ };
|
|
|
+
|
|
|
+ if (cia->cia_err & (CIA_ERR_COR_ERR
|
|
|
+ | CIA_ERR_UN_COR_ERR
|
|
|
+ | CIA_ERR_MEM_NEM
|
|
|
+ | CIA_ERR_PA_PTE_INV)) {
|
|
|
+ static const char * const window_desc[6] = {
|
|
|
+ "No window active", "Window 0 hit", "Window 1 hit",
|
|
|
+ "Window 2 hit", "Window 3 hit", "Monster window hit"
|
|
|
+ };
|
|
|
+
|
|
|
+ const char *window;
|
|
|
+ const char *cmd;
|
|
|
+ unsigned long addr, tmp;
|
|
|
+ int lock, dac;
|
|
|
+
|
|
|
+ cmd = pci_cmd_desc[cia->pci_err0 & 0x7];
|
|
|
+ lock = (cia->pci_err0 >> 4) & 1;
|
|
|
+ dac = (cia->pci_err0 >> 5) & 1;
|
|
|
+
|
|
|
+ tmp = (cia->pci_err0 >> 8) & 0x1F;
|
|
|
+ tmp = ffs(tmp);
|
|
|
+ window = window_desc[tmp];
|
|
|
+
|
|
|
+ addr = cia->pci_err1;
|
|
|
+ if (dac) {
|
|
|
+ tmp = *(vip)CIA_IOC_PCI_W_DAC & 0xFFUL;
|
|
|
+ addr |= tmp << 32;
|
|
|
+ }
|
|
|
+
|
|
|
+ printk(KERN_CRIT "CIA machine check: %s\n", msg);
|
|
|
+ printk(KERN_CRIT " DMA command: %s\n", cmd);
|
|
|
+ printk(KERN_CRIT " PCI address: %#010lx\n", addr);
|
|
|
+ printk(KERN_CRIT " %s, Lock: %d, DAC: %d\n",
|
|
|
+ window, lock, dac);
|
|
|
+ } else if (cia->cia_err & (CIA_ERR_PERR
|
|
|
+ | CIA_ERR_PCI_ADDR_PE
|
|
|
+ | CIA_ERR_RCVD_MAS_ABT
|
|
|
+ | CIA_ERR_RCVD_TAR_ABT
|
|
|
+ | CIA_ERR_IOA_TIMEOUT)) {
|
|
|
+ static const char * const master_st_desc[16] = {
|
|
|
+ "Idle", "Drive bus", "Address step cycle",
|
|
|
+ "Address cycle", "Data cycle", "Last read data cycle",
|
|
|
+ "Last write data cycle", "Read stop cycle",
|
|
|
+ "Write stop cycle", "Read turnaround cycle",
|
|
|
+ "Write turnaround cycle", "Reserved 0xB",
|
|
|
+ "Reserved 0xC", "Reserved 0xD", "Reserved 0xE",
|
|
|
+ "Unknown state"
|
|
|
+ };
|
|
|
+ static const char * const target_st_desc[16] = {
|
|
|
+ "Idle", "Busy", "Read data cycle", "Write data cycle",
|
|
|
+ "Read stop cycle", "Write stop cycle",
|
|
|
+ "Read turnaround cycle", "Write turnaround cycle",
|
|
|
+ "Read wait cycle", "Write wait cycle",
|
|
|
+ "Reserved 0xA", "Reserved 0xB", "Reserved 0xC",
|
|
|
+ "Reserved 0xD", "Reserved 0xE", "Unknown state"
|
|
|
+ };
|
|
|
+
|
|
|
+ const char *cmd;
|
|
|
+ const char *master, *target;
|
|
|
+ unsigned long addr, tmp;
|
|
|
+ int dac;
|
|
|
+
|
|
|
+ master = master_st_desc[(cia->pci_err0 >> 16) & 0xF];
|
|
|
+ target = target_st_desc[(cia->pci_err0 >> 20) & 0xF];
|
|
|
+ cmd = pci_cmd_desc[(cia->pci_err0 >> 24) & 0xF];
|
|
|
+ dac = (cia->pci_err0 >> 28) & 1;
|
|
|
+
|
|
|
+ addr = cia->pci_err2;
|
|
|
+ if (dac) {
|
|
|
+ tmp = *(volatile int *)CIA_IOC_PCI_W_DAC & 0xFFUL;
|
|
|
+ addr |= tmp << 32;
|
|
|
+ }
|
|
|
+
|
|
|
+ printk(KERN_CRIT "CIA machine check: %s\n", msg);
|
|
|
+ printk(KERN_CRIT " PCI command: %s\n", cmd);
|
|
|
+ printk(KERN_CRIT " Master state: %s, Target state: %s\n",
|
|
|
+ master, target);
|
|
|
+ printk(KERN_CRIT " PCI address: %#010lx, DAC: %d\n",
|
|
|
+ addr, dac);
|
|
|
+ } else {
|
|
|
+ printk(KERN_CRIT "CIA machine check: %s\n", msg);
|
|
|
+ printk(KERN_CRIT " Unknown PCI error\n");
|
|
|
+ printk(KERN_CRIT " PCI_ERR0 = %#08lx", cia->pci_err0);
|
|
|
+ printk(KERN_CRIT " PCI_ERR1 = %#08lx", cia->pci_err1);
|
|
|
+ printk(KERN_CRIT " PCI_ERR2 = %#08lx", cia->pci_err2);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+cia_decode_mem_error(struct el_CIA_sysdata_mcheck *cia, const char *msg)
|
|
|
+{
|
|
|
+ unsigned long mem_port_addr;
|
|
|
+ unsigned long mem_port_mask;
|
|
|
+ const char *mem_port_cmd;
|
|
|
+ const char *seq_state;
|
|
|
+ const char *set_select;
|
|
|
+ unsigned long tmp;
|
|
|
+
|
|
|
+ /* If this is a DMA command, also decode the PCI bits. */
|
|
|
+ if ((cia->mem_err1 >> 20) & 1)
|
|
|
+ cia_decode_pci_error(cia, msg);
|
|
|
+ else
|
|
|
+ printk(KERN_CRIT "CIA machine check: %s\n", msg);
|
|
|
+
|
|
|
+ mem_port_addr = cia->mem_err0 & 0xfffffff0;
|
|
|
+ mem_port_addr |= (cia->mem_err1 & 0x83UL) << 32;
|
|
|
+
|
|
|
+ mem_port_mask = (cia->mem_err1 >> 12) & 0xF;
|
|
|
+
|
|
|
+ tmp = (cia->mem_err1 >> 8) & 0xF;
|
|
|
+ tmp |= ((cia->mem_err1 >> 20) & 1) << 4;
|
|
|
+ if ((tmp & 0x1E) == 0x06)
|
|
|
+ mem_port_cmd = "WRITE BLOCK or WRITE BLOCK LOCK";
|
|
|
+ else if ((tmp & 0x1C) == 0x08)
|
|
|
+ mem_port_cmd = "READ MISS or READ MISS MODIFY";
|
|
|
+ else if (tmp == 0x1C)
|
|
|
+ mem_port_cmd = "BC VICTIM";
|
|
|
+ else if ((tmp & 0x1E) == 0x0E)
|
|
|
+ mem_port_cmd = "READ MISS MODIFY";
|
|
|
+ else if ((tmp & 0x1C) == 0x18)
|
|
|
+ mem_port_cmd = "DMA READ or DMA READ MODIFY";
|
|
|
+ else if ((tmp & 0x1E) == 0x12)
|
|
|
+ mem_port_cmd = "DMA WRITE";
|
|
|
+ else
|
|
|
+ mem_port_cmd = "Unknown";
|
|
|
+
|
|
|
+ tmp = (cia->mem_err1 >> 16) & 0xF;
|
|
|
+ switch (tmp) {
|
|
|
+ case 0x0:
|
|
|
+ seq_state = "Idle";
|
|
|
+ break;
|
|
|
+ case 0x1:
|
|
|
+ seq_state = "DMA READ or DMA WRITE";
|
|
|
+ break;
|
|
|
+ case 0x2: case 0x3:
|
|
|
+ seq_state = "READ MISS (or READ MISS MODIFY) with victim";
|
|
|
+ break;
|
|
|
+ case 0x4: case 0x5: case 0x6:
|
|
|
+ seq_state = "READ MISS (or READ MISS MODIFY) with no victim";
|
|
|
+ break;
|
|
|
+ case 0x8: case 0x9: case 0xB:
|
|
|
+ seq_state = "Refresh";
|
|
|
+ break;
|
|
|
+ case 0xC:
|
|
|
+ seq_state = "Idle, waiting for DMA pending read";
|
|
|
+ break;
|
|
|
+ case 0xE: case 0xF:
|
|
|
+ seq_state = "Idle, ras precharge";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ seq_state = "Unknown";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ tmp = (cia->mem_err1 >> 24) & 0x1F;
|
|
|
+ switch (tmp) {
|
|
|
+ case 0x00: set_select = "Set 0 selected"; break;
|
|
|
+ case 0x01: set_select = "Set 1 selected"; break;
|
|
|
+ case 0x02: set_select = "Set 2 selected"; break;
|
|
|
+ case 0x03: set_select = "Set 3 selected"; break;
|
|
|
+ case 0x04: set_select = "Set 4 selected"; break;
|
|
|
+ case 0x05: set_select = "Set 5 selected"; break;
|
|
|
+ case 0x06: set_select = "Set 6 selected"; break;
|
|
|
+ case 0x07: set_select = "Set 7 selected"; break;
|
|
|
+ case 0x08: set_select = "Set 8 selected"; break;
|
|
|
+ case 0x09: set_select = "Set 9 selected"; break;
|
|
|
+ case 0x0A: set_select = "Set A selected"; break;
|
|
|
+ case 0x0B: set_select = "Set B selected"; break;
|
|
|
+ case 0x0C: set_select = "Set C selected"; break;
|
|
|
+ case 0x0D: set_select = "Set D selected"; break;
|