patch-2.4.21 linux-2.4.21/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c
Next file: linux-2.4.21/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c
Previous file: linux-2.4.21/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
Back to the patch index
Back to the overall index
- Lines: 1441
- Date:
2003-06-13 07:51:31.000000000 -0700
- Orig file:
linux-2.4.20/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c
- Orig date:
2002-08-02 17:39:43.000000000 -0700
diff -urN linux-2.4.20/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c linux-2.4.21/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c
@@ -39,6 +39,14 @@
#endif
extern int hubii_check_widget_disabled(nasid_t, int);
+#ifdef BRIDGE_B_DATACORR_WAR
+extern int ql_bridge_rev_b_war(devfs_handle_t);
+extern int bridge_rev_b_data_check_disable;
+char *rev_b_datacorr_warning =
+"***************************** WARNING! ******************************\n";
+char *rev_b_datacorr_mesg =
+"UNRECOVERABLE IO LINK ERROR. CONTACT SERVICE PROVIDER\n";
+#endif
/* =====================================================================
* ERROR HANDLING
@@ -54,15 +62,18 @@
#define BRIDGE_PIOERR_TIMEOUT 1 /* Timeout in non-debug mode */
#endif
+/* PIC has 64bit interrupt error registers, but BRIDGE has 32bit registers.
+ * Thus 'bridge_errors_to_dump needs' to default to the larger of the two.
+ */
#ifdef DEBUG
#ifdef ERROR_DEBUG
-bridgereg_t bridge_errors_to_dump = ~BRIDGE_ISR_INT_MSK;
+uint64_t bridge_errors_to_dump = ~BRIDGE_ISR_INT_MSK;
#else
-bridgereg_t bridge_errors_to_dump = BRIDGE_ISR_ERROR_DUMP;
+uint64_t bridge_errors_to_dump = BRIDGE_ISR_ERROR_DUMP;
#endif
#else
-bridgereg_t bridge_errors_to_dump = BRIDGE_ISR_ERROR_FATAL |
- BRIDGE_ISR_PCIBUS_PIOERR;
+uint64_t bridge_errors_to_dump = BRIDGE_ISR_ERROR_FATAL |
+ BRIDGE_ISR_PCIBUS_PIOERR;
#endif
#if defined (PCIBR_LLP_CONTROL_WAR)
@@ -71,8 +82,6 @@
/* FIXME: can these arrays be local ? */
-#ifdef LATER
-
struct reg_values xio_cmd_pactyp[] =
{
{0x0, "RdReq"},
@@ -113,7 +122,21 @@
struct reg_desc bridge_int_status_desc[] =
{
- F(31, "MULTI_ERR"),
+ F(45, "PCI_X_SPLIT_MES_PE"),/* PIC ONLY */
+ F(44, "PCI_X_SPLIT_EMES"), /* PIC ONLY */
+ F(43, "PCI_X_SPLIT_TO"), /* PIC ONLY */
+ F(42, "PCI_X_UNEX_COMP"), /* PIC ONLY */
+ F(41, "INT_RAM_PERR"), /* PIC ONLY */
+ F(40, "PCI_X_ARB_ERR"), /* PIC ONLY */
+ F(39, "PCI_X_REQ_TOUT"), /* PIC ONLY */
+ F(38, "PCI_X_TABORT"), /* PIC ONLY */
+ F(37, "PCI_X_PERR"), /* PIC ONLY */
+ F(36, "PCI_X_SERR"), /* PIC ONLY */
+ F(35, "PCI_X_MRETRY"), /* PIC ONLY */
+ F(34, "PCI_X_MTOUT"), /* PIC ONLY */
+ F(33, "PCI_X_DA_PARITY"), /* PIC ONLY */
+ F(32, "PCI_X_AD_PARITY"), /* PIC ONLY */
+ F(31, "MULTI_ERR"), /* BRIDGE ONLY */
F(30, "PMU_ESIZE_EFAULT"),
F(29, "UNEXPECTED_RESP"),
F(28, "BAD_XRESP_PACKET"),
@@ -128,7 +151,7 @@
F(19, "LLP_RCTY"),
F(18, "LLP_TX_RETRY"),
F(17, "LLP_TCTY"),
- F(16, "SSRAM_PERR"),
+ F(16, "SSRAM_PERR"), /* BRIDGE ONLY */
F(15, "PCI_ABORT"),
F(14, "PCI_PARITY"),
F(13, "PCI_SERR"),
@@ -136,7 +159,7 @@
F(11, "PCI_MASTER_TOUT"),
F(10, "PCI_RETRY_CNT"),
F(9, "XREAD_REQ_TOUT"),
- F(8, "GIO_BENABLE_ERR"),
+ F(8, "GIO_BENABLE_ERR"), /* BRIDGE ONLY */
F(7, "INT7"),
F(6, "INT6"),
F(5, "INT5"),
@@ -195,20 +218,17 @@
{0}
};
-#endif /* LATER */
-
void
print_bridge_errcmd(uint32_t cmdword, char *errtype)
{
- printk(
- "\t Bridge %s Error Command Word Register %R\n",
- errtype, cmdword, xio_cmd_bits);
+ printk("\t Bridge %s Error Command Word Register ", errtype);
+ print_register(cmdword, xio_cmd_bits);
}
char *pcibr_isr_errs[] =
{
"", "", "", "", "", "", "", "",
- "08: GIO non-contiguous byte enable in crosstalk packet",
+ "08: GIO non-contiguous byte enable in crosstalk packet", /* BRIDGE ONLY */
"09: PCI to Crosstalk read request timeout",
"10: PCI retry operation count exhausted.",
"11: PCI bus device select timeout",
@@ -216,7 +236,7 @@
"13: PCI Address/Cmd parity error ",
"14: PCI Bridge detected parity error",
"15: PCI abort condition",
- "16: SSRAM parity error",
+ "16: SSRAM parity error", /* BRIDGE ONLY */
"17: LLP Transmitter Retry count wrapped",
"18: LLP Transmitter side required Retry",
"19: LLP Receiver retry count wrapped",
@@ -231,13 +251,29 @@
"28: Framing error, response cmd data size does not match actual",
"29: Unexpected response arrived",
"30: PMU Access Fault",
- "31: Multiple errors occurred",
+ "31: Multiple errors occurred", /* BRIDGE ONLY */
+
+ /* bits 32-45 are PIC ONLY */
+ "32: PCI-X address or attribute cycle parity error",
+ "33: PCI-X data cycle parity error",
+ "34: PCI-X master timeout (ie. master abort)",
+ "35: PCI-X pio retry counter exhausted",
+ "36: PCI-X SERR",
+ "37: PCI-X PERR",
+ "38: PCI-X target abort",
+ "39: PCI-X read request timeout",
+ "40: PCI / PCI-X device requestin arbitration error",
+ "41: internal RAM parity error",
+ "42: PCI-X unexpected completion cycle to master",
+ "43: PCI-X split completion timeout",
+ "44: PCI-X split completion error message",
+ "45: PCI-X split completion message parity error",
};
#define BEM_ADD_STR(s) printk("%s", (s))
-#define BEM_ADD_VAR(v) printk("\t%20s: 0x%x\n", #v, (v))
-#define BEM_ADD_REG(r) printk("\t%20s: %R\n", #r, (r), r ## _desc)
-#define BEM_ADD_NSPC(n,s) printk("\t%20s: %R\n", n, s, space_desc)
+#define BEM_ADD_VAR(v) printk("\t%20s: 0x%llx\n", #v, ((unsigned long long)v))
+#define BEM_ADD_REG(r) printk("\t%20s: ", #r); print_register((r), r ## _desc)
+#define BEM_ADD_NSPC(n,s) printk("\t%20s: ", n); print_register(s, space_desc)
#define BEM_ADD_SPC(s) BEM_ADD_NSPC(#s, s)
/*
@@ -246,6 +282,7 @@
void
pcibr_show_dir_state(paddr_t paddr, char *prefix)
{
+#ifdef LATER
int state;
uint64_t vec_ptr;
hubreg_t elo;
@@ -254,8 +291,9 @@
get_dir_ent(paddr, &state, &vec_ptr, &elo);
- printf("%saddr 0x%x: state 0x%x owner 0x%x (%s)\n",
+ printk("%saddr 0x%lx: state 0x%x owner 0x%lx (%s)\n",
prefix, paddr, state, vec_ptr, dir_state_str[state]);
+#endif
}
@@ -267,40 +305,70 @@
pcibr_error_dump(pcibr_soft_t pcibr_soft)
{
bridge_t *bridge = pcibr_soft->bs_base;
- bridgereg_t int_status;
- bridgereg_t mult_int;
- int bit;
+ uint64_t int_status;
+ bridgereg_t int_status_32;
+ picreg_t int_status_64;
+ uint64_t mult_int;
+ bridgereg_t mult_int_32;
+ picreg_t mult_int_64;
+ uint64_t bit;
+ int number_bits;
int i;
char *reg_desc;
- paddr_t addr;
+ paddr_t addr = (paddr_t)0;
+
+ /* We read the INT_STATUS register as a 64bit picreg_t for PIC and a
+ * 32bit bridgereg_t for BRIDGE, but always process the result as a
+ * 64bit value so the code can be "common" for both PIC and BRIDGE...
+ */
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ int_status_64 = (bridge->p_int_status_64 & ~BRIDGE_ISR_INT_MSK);
+ int_status = (uint64_t)int_status_64;
+ number_bits = PCIBR_ISR_MAX_ERRS_PIC;
+ } else {
+ int_status_32 = (bridge->b_int_status & ~BRIDGE_ISR_INT_MSK);
+ int_status = ((uint64_t)int_status_32) & 0xffffffff;
+ number_bits = PCIBR_ISR_MAX_ERRS_BRIDGE;
+ }
- int_status = (bridge->b_int_status & ~BRIDGE_ISR_INT_MSK);
if (!int_status) {
/* No error bits set */
return;
}
/* Check if dumping the same error information multiple times */
- if (test_and_set_int((int *) &pcibr_soft->bs_errinfo.bserr_intstat,
- int_status) == int_status) {
+ if ( pcibr_soft->bs_errinfo.bserr_intstat == int_status )
return;
- }
+ pcibr_soft->bs_errinfo.bserr_intstat = int_status;
- printk(KERN_ALERT "PCI BRIDGE ERROR: int_status is 0x%X for %s\n"
- " Dumping relevant %sBridge registers for each bit set...\n",
+ printk(KERN_ALERT "PCI BRIDGE ERROR: int_status is 0x%lx for %s\n"
+ " Dumping relevant %s registers for each bit set...\n",
int_status, pcibr_soft->bs_name,
- (is_xbridge(bridge) ? "X" : ""));
+ (IS_PIC_SOFT(pcibr_soft) ? "PIC" :
+ (IS_BRIDGE_SOFT(pcibr_soft) ? "BRIDGE" : "XBRIDGE")));
- for (i = PCIBR_ISR_ERR_START; i < PCIBR_ISR_MAX_ERRS; i++) {
- bit = 1 << i;
+ for (i = PCIBR_ISR_ERR_START; i < number_bits; i++) {
+ bit = 1ull << i;
/*
* A number of int_status bits are only defined for Bridge.
- * Ignore them in the case of an XBridge.
+ * Ignore them in the case of an XBridge or PIC.
*/
- if (is_xbridge(bridge) && ((bit == BRIDGE_ISR_MULTI_ERR) ||
- (bit == BRIDGE_ISR_SSRAM_PERR) ||
- (bit == BRIDGE_ISR_GIO_B_ENBL_ERR))) {
+ if ((IS_XBRIDGE_SOFT(pcibr_soft) || IS_PIC_SOFT(pcibr_soft)) &&
+ ((bit == BRIDGE_ISR_MULTI_ERR) ||
+ (bit == BRIDGE_ISR_SSRAM_PERR) ||
+ (bit == BRIDGE_ISR_GIO_B_ENBL_ERR))) {
+ continue;
+ }
+
+ /* A number of int_status bits are only valid for PIC's bus0 */
+ if ((IS_PIC_SOFT(pcibr_soft) && (pcibr_soft->bs_busnum != 0)) &&
+ ((bit == BRIDGE_ISR_UNSUPPORTED_XOP) ||
+ (bit == BRIDGE_ISR_LLP_REC_SNERR) ||
+ (bit == BRIDGE_ISR_LLP_REC_CBERR) ||
+ (bit == BRIDGE_ISR_LLP_RCTY) ||
+ (bit == BRIDGE_ISR_LLP_TX_RETRY) ||
+ (bit == BRIDGE_ISR_LLP_TCTY))) {
continue;
}
@@ -308,91 +376,241 @@
printk("\t%s\n", pcibr_isr_errs[i]);
switch (bit) {
- case BRIDGE_ISR_PAGE_FAULT: /* PMU_PAGE_FAULT (XBridge) */
-/* case BRIDGE_ISR_PMU_ESIZE_FAULT: PMU_ESIZE_FAULT (Bridge) */
- if (is_xbridge(bridge))
+
+ case PIC_ISR_INT_RAM_PERR: /* bit41 INT_RAM_PERR */
+ /* XXX: should breakdown meaning of bits in reg */
+ printk( "\t Internal RAM Parity Error: 0x%lx\n",
+ bridge->p_ate_parity_err_64);
+ break;
+
+ case PIC_ISR_PCIX_ARB_ERR: /* bit40 PCI_X_ARB_ERR */
+ /* XXX: should breakdown meaning of bits in reg */
+ printk( "\t Arbitration Reg: 0x%x\n",
+ bridge->b_arb);
+ break;
+
+ case PIC_ISR_PCIX_REQ_TOUT: /* bit39 PCI_X_REQ_TOUT */
+ /* XXX: should breakdown meaning of attribute bit */
+ printk(
+ "\t PCI-X DMA Request Error Address Reg: 0x%lx\n"
+ "\t PCI-X DMA Request Error Attribute Reg: 0x%lx\n",
+ bridge->p_pcix_dma_req_err_addr_64,
+ bridge->p_pcix_dma_req_err_attr_64);
+ break;
+
+ case PIC_ISR_PCIX_SPLIT_MSG_PE: /* bit45 PCI_X_SPLIT_MES_PE */
+ case PIC_ISR_PCIX_SPLIT_EMSG: /* bit44 PCI_X_SPLIT_EMESS */
+ case PIC_ISR_PCIX_SPLIT_TO: /* bit43 PCI_X_SPLIT_TO */
+ /* XXX: should breakdown meaning of attribute bit */
+ printk(
+ "\t PCI-X Split Request Address Reg: 0x%lx\n"
+ "\t PCI-X Split Request Attribute Reg: 0x%lx\n",
+ bridge->p_pcix_pio_split_addr_64,
+ bridge->p_pcix_pio_split_attr_64);
+ /* FALL THRU */
+
+ case PIC_ISR_PCIX_UNEX_COMP: /* bit42 PCI_X_UNEX_COMP */
+ case PIC_ISR_PCIX_TABORT: /* bit38 PCI_X_TABORT */
+ case PIC_ISR_PCIX_PERR: /* bit37 PCI_X_PERR */
+ case PIC_ISR_PCIX_SERR: /* bit36 PCI_X_SERR */
+ case PIC_ISR_PCIX_MRETRY: /* bit35 PCI_X_MRETRY */
+ case PIC_ISR_PCIX_MTOUT: /* bit34 PCI_X_MTOUT */
+ case PIC_ISR_PCIX_DA_PARITY: /* bit33 PCI_X_DA_PARITY */
+ case PIC_ISR_PCIX_AD_PARITY: /* bit32 PCI_X_AD_PARITY */
+ /* XXX: should breakdown meaning of attribute bit */
+ printk(
+ "\t PCI-X Bus Error Address Reg: 0x%lx\n"
+ "\t PCI-X Bus Error Attribute Reg: 0x%lx\n"
+ "\t PCI-X Bus Error Data Reg: 0x%lx\n",
+ bridge->p_pcix_bus_err_addr_64,
+ bridge->p_pcix_bus_err_attr_64,
+ bridge->p_pcix_bus_err_data_64);
+ break;
+
+ case BRIDGE_ISR_PAGE_FAULT: /* bit30 PMU_PAGE_FAULT */
+/* case BRIDGE_ISR_PMU_ESIZE_FAULT: bit30 PMU_ESIZE_FAULT */
+ if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft))
reg_desc = "Map Fault Address";
else
reg_desc = "SSRAM Parity Error";
- printk("\t %s Register: 0x%x\n", reg_desc,
+ printk( "\t %s Register: 0x%x\n", reg_desc,
bridge->b_ram_perr_or_map_fault);
break;
- case BRIDGE_ISR_UNEXP_RESP: /* UNEXPECTED_RESP */
- print_bridge_errcmd(bridge->b_wid_aux_err, "Aux");
- break;
+ case BRIDGE_ISR_UNEXP_RESP: /* bit29 UNEXPECTED_RESP */
+ print_bridge_errcmd(bridge->b_wid_aux_err, "Aux ");
- case BRIDGE_ISR_BAD_XRESP_PKT: /* BAD_RESP_PACKET */
- case BRIDGE_ISR_RESP_XTLK_ERR: /* RESP_XTALK_ERROR */
- case BRIDGE_ISR_XREAD_REQ_TIMEOUT: /* XREAD_REQ_TOUT */
+ /* PIC in PCI-X mode, dump the PCIX DMA Request registers */
+ if (IS_PIC_SOFT(pcibr_soft) && IS_PCIX(pcibr_soft)) {
+ /* XXX: should breakdown meaning of attr bit */
+ printk(
+ "\t PCI-X DMA Request Error Addr Reg: 0x%lx\n"
+ "\t PCI-X DMA Request Error Attr Reg: 0x%lx\n",
+ bridge->p_pcix_dma_req_err_addr_64,
+ bridge->p_pcix_dma_req_err_attr_64);
+ }
+ break;
- addr = (((uint64_t) (bridge->b_wid_resp_upper & 0xFFFF) << 32)
- | bridge->b_wid_resp_lower);
- printk(
- "\t Bridge Response Buffer Error Upper Address Register: 0x%x\n"
- "\t Bridge Response Buffer Error Lower Address Register: 0x%x\n"
- "\t dev-num %d buff-num %d addr 0x%x\n",
- bridge->b_wid_resp_upper, bridge->b_wid_resp_lower,
- ((bridge->b_wid_resp_upper >> 20) & 0x3),
- ((bridge->b_wid_resp_upper >> 16) & 0xF),
- addr);
+ case BRIDGE_ISR_BAD_XRESP_PKT: /* bit28 BAD_RESP_PACKET */
+ case BRIDGE_ISR_RESP_XTLK_ERR: /* bit26 RESP_XTALK_ERROR */
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ print_bridge_errcmd(bridge->b_wid_aux_err, "Aux ");
+ }
+
+ /* If PIC in PCI-X mode, DMA Request Error registers are
+ * valid. But PIC in PCI mode, Response Buffer Address
+ * register are valid.
+ */
+ if (IS_PCIX(pcibr_soft)) {
+ /* XXX: should breakdown meaning of attribute bit */
+ printk(
+ "\t PCI-X DMA Request Error Addr Reg: 0x%lx\n"
+ "\t PCI-X DMA Request Error Attribute Reg: 0x%lx\n",
+ bridge->p_pcix_dma_req_err_addr_64,
+ bridge->p_pcix_dma_req_err_attr_64);
+ } else {
+ addr= (((uint64_t)(bridge->b_wid_resp_upper & 0xFFFF)<<32)
+ | bridge->b_wid_resp_lower);
+ printk("\t Bridge Response Buf Error Upper Addr Reg: 0x%x\n"
+ "\t Bridge Response Buf Error Lower Addr Reg: 0x%x\n"
+ "\t dev-num %d buff-num %d addr 0x%lx\n",
+ bridge->b_wid_resp_upper, bridge->b_wid_resp_lower,
+ ((bridge->b_wid_resp_upper >> 20) & 0x3),
+ ((bridge->b_wid_resp_upper >> 16) & 0xF),
+ addr);
+ }
if (bit == BRIDGE_ISR_RESP_XTLK_ERR) {
/* display memory directory associated with cacheline */
pcibr_show_dir_state(addr, "\t ");
}
break;
- case BRIDGE_ISR_BAD_XREQ_PKT: /* BAD_XREQ_PACKET */
- case BRIDGE_ISR_REQ_XTLK_ERR: /* REQ_XTALK_ERROR */
- case BRIDGE_ISR_INVLD_ADDR: /* INVALID_ADDRESS */
- case BRIDGE_ISR_UNSUPPORTED_XOP: /* UNSUPPORTED_XOP */
- print_bridge_errcmd(bridge->b_wid_aux_err, "");
- printk("\t Bridge Error Upper Address Register: 0x%x\n"
- "\t Bridge Error Lower Address Register: 0x%x\n"
- "\t Bridge Error Address: 0x%x\n",
+ case BRIDGE_ISR_BAD_XREQ_PKT: /* bit27 BAD_XREQ_PACKET */
+ case BRIDGE_ISR_REQ_XTLK_ERR: /* bit25 REQ_XTALK_ERROR */
+ case BRIDGE_ISR_INVLD_ADDR: /* bit24 INVALID_ADDRESS */
+ print_bridge_errcmd(bridge->b_wid_err_cmdword, "");
+ printk(
+ "\t Bridge Error Upper Address Register: 0x%lx\n"
+ "\t Bridge Error Lower Address Register: 0x%lx\n"
+ "\t Bridge Error Address: 0x%lx\n",
(uint64_t) bridge->b_wid_err_upper,
(uint64_t) bridge->b_wid_err_lower,
(((uint64_t) bridge->b_wid_err_upper << 32) |
bridge->b_wid_err_lower));
break;
- case BRIDGE_ISR_SSRAM_PERR: /* SSRAM_PERR */
- if (!is_xbridge(bridge)) { /* only defined on Bridge */
+ case BRIDGE_ISR_UNSUPPORTED_XOP:/* bit23 UNSUPPORTED_XOP */
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ print_bridge_errcmd(bridge->b_wid_aux_err, "Aux ");
+ printk(
+ "\t Address Holding Link Side Error Reg: 0x%lx\n",
+ bridge->p_addr_lkerr_64);
+ } else {
+ print_bridge_errcmd(bridge->b_wid_err_cmdword, "");
+ printk(
+ "\t Bridge Error Upper Address Register: 0x%lx\n"
+ "\t Bridge Error Lower Address Register: 0x%lx\n"
+ "\t Bridge Error Address: 0x%lx\n",
+ (uint64_t) bridge->b_wid_err_upper,
+ (uint64_t) bridge->b_wid_err_lower,
+ (((uint64_t) bridge->b_wid_err_upper << 32) |
+ bridge->b_wid_err_lower));
+ }
+ break;
+
+ case BRIDGE_ISR_XREQ_FIFO_OFLOW:/* bit22 XREQ_FIFO_OFLOW */
+ /* Link side error registers are only valid for PIC */
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ print_bridge_errcmd(bridge->b_wid_aux_err, "Aux ");
+ printk(
+ "\t Address Holding Link Side Error Reg: 0x%lx\n",
+ bridge->p_addr_lkerr_64);
+ }
+ break;
+
+ case BRIDGE_ISR_SSRAM_PERR: /* bit16 SSRAM_PERR */
+ if (IS_BRIDGE_SOFT(pcibr_soft)) {
printk(
"\t Bridge SSRAM Parity Error Register: 0x%x\n",
bridge->b_ram_perr);
}
break;
- case BRIDGE_ISR_PCI_ABORT: /* PCI_ABORT */
- case BRIDGE_ISR_PCI_PARITY: /* PCI_PARITY */
- case BRIDGE_ISR_PCI_SERR: /* PCI_SERR */
- case BRIDGE_ISR_PCI_PERR: /* PCI_PERR */
- case BRIDGE_ISR_PCI_MST_TIMEOUT: /* PCI_MASTER_TOUT */
- case BRIDGE_ISR_PCI_RETRY_CNT: /* PCI_RETRY_CNT */
- case BRIDGE_ISR_GIO_B_ENBL_ERR: /* GIO BENABLE_ERR */
- printk("\t PCI Error Upper Address Register: 0x%x\n"
- "\t PCI Error Lower Address Register: 0x%x\n"
- "\t PCI Error Address: 0x%x\n",
+ case BRIDGE_ISR_PCI_ABORT: /* bit15 PCI_ABORT */
+ case BRIDGE_ISR_PCI_PARITY: /* bit14 PCI_PARITY */
+ case BRIDGE_ISR_PCI_SERR: /* bit13 PCI_SERR */
+ case BRIDGE_ISR_PCI_PERR: /* bit12 PCI_PERR */
+ case BRIDGE_ISR_PCI_MST_TIMEOUT:/* bit11 PCI_MASTER_TOUT */
+ case BRIDGE_ISR_PCI_RETRY_CNT: /* bit10 PCI_RETRY_CNT */
+ case BRIDGE_ISR_GIO_B_ENBL_ERR: /* bit08 GIO BENABLE_ERR */
+ printk(
+ "\t PCI Error Upper Address Register: 0x%lx\n"
+ "\t PCI Error Lower Address Register: 0x%lx\n"
+ "\t PCI Error Address: 0x%lx\n",
(uint64_t) bridge->b_pci_err_upper,
(uint64_t) bridge->b_pci_err_lower,
(((uint64_t) bridge->b_pci_err_upper << 32) |
bridge->b_pci_err_lower));
break;
+
+ case BRIDGE_ISR_XREAD_REQ_TIMEOUT: /* bit09 XREAD_REQ_TOUT */
+ addr = (((uint64_t)(bridge->b_wid_resp_upper & 0xFFFF) << 32)
+ | bridge->b_wid_resp_lower);
+ printk(
+ "\t Bridge Response Buf Error Upper Addr Reg: 0x%x\n"
+ "\t Bridge Response Buf Error Lower Addr Reg: 0x%x\n"
+ "\t dev-num %d buff-num %d addr 0x%lx\n",
+ bridge->b_wid_resp_upper, bridge->b_wid_resp_lower,
+ ((bridge->b_wid_resp_upper >> 20) & 0x3),
+ ((bridge->b_wid_resp_upper >> 16) & 0xF),
+ addr);
+ break;
}
}
}
- if (is_xbridge(bridge) && (bridge->b_mult_int & ~BRIDGE_ISR_INT_MSK)) {
- mult_int = bridge->b_mult_int;
- printk(" XBridge Multiple Interrupt Register is 0x%x\n",
- mult_int);
- for (i = PCIBR_ISR_ERR_START; i < PCIBR_ISR_MAX_ERRS; i++) {
- if (mult_int & (1 << i))
- printk("\t%s\n", pcibr_isr_errs[i]);
- }
+ /* We read the INT_MULT register as a 64bit picreg_t for PIC and a
+ * 32bit bridgereg_t for BRIDGE, but always process the result as a
+ * 64bit value so the code can be "common" for both PIC and BRIDGE...
+ */
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ mult_int_64 = (bridge->p_mult_int_64 & ~BRIDGE_ISR_INT_MSK);
+ mult_int = (uint64_t)mult_int_64;
+ number_bits = PCIBR_ISR_MAX_ERRS_PIC;
+ } else {
+ mult_int_32 = (bridge->b_mult_int & ~BRIDGE_ISR_INT_MSK);
+ mult_int = ((uint64_t)mult_int_32) & 0xffffffff;
+ number_bits = PCIBR_ISR_MAX_ERRS_BRIDGE;
+ }
+
+ if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)&&(mult_int & ~BRIDGE_ISR_INT_MSK)) {
+ printk( " %s Multiple Interrupt Register is 0x%lx\n",
+ IS_PIC_SOFT(pcibr_soft) ? "PIC" : "XBridge", mult_int);
+ for (i = PCIBR_ISR_ERR_START; i < number_bits; i++) {
+ if (mult_int & (1ull << i))
+ printk( "\t%s\n", pcibr_isr_errs[i]);
}
+ }
+
+#if BRIDGE_ERROR_INTR_WAR
+ if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_A) { /* known bridge bug */
+ /*
+ * Should never receive interrupts for these reasons on Rev 1 bridge
+ * as they are not enabled. Assert for it.
+ */
+ ASSERT((int_status & (BRIDGE_IMR_PCI_MST_TIMEOUT |
+ BRIDGE_ISR_RESP_XTLK_ERR |
+ BRIDGE_ISR_LLP_TX_RETRY)) == 0);
+ }
+ if (pcibr_soft->bs_rev_num < BRIDGE_PART_REV_C) { /* known bridge bug */
+ /*
+ * This interrupt is turned off at init time. So, should never
+ * see this interrupt.
+ */
+ ASSERT((int_status & BRIDGE_ISR_BAD_XRESP_PKT) == 0);
+ }
+#endif
}
#define PCIBR_ERRINTR_GROUP(error) \
@@ -430,9 +648,11 @@
pcibr_pioerr_check(pcibr_soft_t soft)
{
bridge_t *bridge;
- bridgereg_t b_int_status;
- bridgereg_t b_pci_err_lower;
- bridgereg_t b_pci_err_upper;
+ uint64_t int_status;
+ bridgereg_t int_status_32;
+ picreg_t int_status_64;
+ bridgereg_t pci_err_lower;
+ bridgereg_t pci_err_upper;
iopaddr_t pci_addr;
pciio_slot_t slot;
pcibr_piomap_t map;
@@ -442,40 +662,48 @@
int func;
bridge = soft->bs_base;
- b_int_status = bridge->b_int_status;
- if (b_int_status & BRIDGE_ISR_PCIBUS_PIOERR) {
- b_pci_err_lower = bridge->b_pci_err_lower;
- b_pci_err_upper = bridge->b_pci_err_upper;
- b_int_status = bridge->b_int_status;
- if (b_int_status & BRIDGE_ISR_PCIBUS_PIOERR) {
-
- pci_addr = b_pci_err_upper & BRIDGE_ERRUPPR_ADDRMASK;
- pci_addr = (pci_addr << 32) | b_pci_err_lower;
-
- slot = 8;
- while (slot-- > 0) {
- int nfunc = soft->bs_slot[slot].bss_ninfo;
- pcibr_info_h pcibr_infoh = soft->bs_slot[slot].bss_infos;
-
- for (func = 0; func < nfunc; func++) {
- pcibr_info_t pcibr_info = pcibr_infoh[func];
-
- if (!pcibr_info)
- continue;
-
- for (map = pcibr_info->f_piomap;
- map != NULL; map = map->bp_next) {
- base = map->bp_pciaddr;
- size = map->bp_mapsz;
- win = map->bp_space - PCIIO_SPACE_WIN(0);
- if (win < 6)
- base +=
- soft->bs_slot[slot].bss_window[win].bssw_base;
- else if (map->bp_space == PCIIO_SPACE_ROM)
- base += pcibr_info->f_rbase;
- if ((pci_addr >= base) && (pci_addr < (base + size)))
- atomicAddInt(map->bp_toc, 1);
- }
+
+ /* We read the INT_STATUS register as a 64bit picreg_t for PIC and a
+ * 32bit bridgereg_t for BRIDGE, but always process the result as a
+ * 64bit value so the code can be "common" for both PIC and BRIDGE...
+ */
+ if (IS_PIC_SOFT(soft)) {
+ int_status_64 = (bridge->p_int_status_64 & ~BRIDGE_ISR_INT_MSK);
+ int_status = (uint64_t)int_status_64;
+ } else {
+ int_status_32 = (bridge->b_int_status & ~BRIDGE_ISR_INT_MSK);
+ int_status = ((uint64_t)int_status_32) & 0xffffffff;
+ }
+
+ if (int_status & BRIDGE_ISR_PCIBUS_PIOERR) {
+ pci_err_lower = bridge->b_pci_err_lower;
+ pci_err_upper = bridge->b_pci_err_upper;
+
+ pci_addr = pci_err_upper & BRIDGE_ERRUPPR_ADDRMASK;
+ pci_addr = (pci_addr << 32) | pci_err_lower;
+
+ slot = PCIBR_NUM_SLOTS(soft);
+ while (slot-- > 0) {
+ int nfunc = soft->bs_slot[slot].bss_ninfo;
+ pcibr_info_h pcibr_infoh = soft->bs_slot[slot].bss_infos;
+
+ for (func = 0; func < nfunc; func++) {
+ pcibr_info_t pcibr_info = pcibr_infoh[func];
+
+ if (!pcibr_info)
+ continue;
+
+ for (map = pcibr_info->f_piomap;
+ map != NULL; map = map->bp_next) {
+ base = map->bp_pciaddr;
+ size = map->bp_mapsz;
+ win = map->bp_space - PCIIO_SPACE_WIN(0);
+ if (win < 6)
+ base += soft->bs_slot[slot].bss_window[win].bssw_base;
+ else if (map->bp_space == PCIIO_SPACE_ROM)
+ base += pcibr_info->f_rbase;
+ if ((pci_addr >= base) && (pci_addr < (base + size)))
+ atomic_inc(&map->bp_toc[0]);
}
}
}
@@ -502,25 +730,33 @@
* due to read or write error!.
*/
-
void
-pcibr_error_intr_handler(intr_arg_t arg)
+pcibr_error_intr_handler(int irq, void *arg, struct pt_regs *ep)
{
pcibr_soft_t pcibr_soft;
bridge_t *bridge;
- bridgereg_t int_status;
- bridgereg_t err_status;
+ uint64_t int_status;
+ uint64_t err_status;
+ bridgereg_t int_status_32;
+ picreg_t int_status_64;
+ int number_bits;
int i;
/* REFERENCED */
- bridgereg_t disable_errintr_mask = 0;
+ uint64_t disable_errintr_mask = 0;
+#ifdef EHE_ENABLE
int rv;
int error_code = IOECODE_DMA | IOECODE_READ;
ioerror_mode_t mode = MODE_DEVERROR;
ioerror_t ioe;
+#endif /* EHE_ENABLE */
nasid_t nasid;
+
#if PCIBR_SOFT_LIST
+ /*
+ * Defensive code for linked pcibr_soft structs
+ */
{
extern pcibr_list_p pcibr_list;
pcibr_list_p entry;
@@ -528,17 +764,14 @@
entry = pcibr_list;
while (1) {
if (entry == NULL) {
- PRINT_PANIC(
- "pcibr_error_intr_handler:\n"
- "\tmy parameter (0x%x) is not a pcibr_soft!",
- arg);
+ PRINT_PANIC("pcibr_error_intr_handler:\tmy parameter (0x%p) is not a pcibr_soft!", arg);
}
if ((intr_arg_t) entry->bl_soft == arg)
break;
entry = entry->bl_next;
}
}
-#endif
+#endif /* PCIBR_SOFT_LIST */
pcibr_soft = (pcibr_soft_t) arg;
bridge = pcibr_soft->bs_base;
@@ -568,16 +801,37 @@
nasid = NASID_GET(bridge);
if (hubii_check_widget_disabled(nasid, pcibr_soft->bs_xid)) {
- timeout(pcibr_error_intr_handler, pcibr_soft, BRIDGE_PIOERR_TIMEOUT);
+ DECLARE_WAIT_QUEUE_HEAD(wq);
+ sleep_on_timeout(&wq, BRIDGE_PIOERR_TIMEOUT*HZ ); /* sleep */
pcibr_soft->bs_errinfo.bserr_toutcnt++;
+ /* Let's go recursive */
+ return(pcibr_error_intr_handler(irq, arg, ep));
+#ifdef LATER
+ timeout(pcibr_error_intr_handler, pcibr_soft, BRIDGE_PIOERR_TIMEOUT);
+#endif
return;
}
+ /* We read the INT_STATUS register as a 64bit picreg_t for PIC and a
+ * 32bit bridgereg_t for BRIDGE, but always process the result as a
+ * 64bit value so the code can be "common" for both PIC and BRIDGE...
+ */
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ int_status_64 = (bridge->p_int_status_64 & ~BRIDGE_ISR_INT_MSK);
+ int_status = (uint64_t)int_status_64;
+ number_bits = PCIBR_ISR_MAX_ERRS_PIC;
+ } else {
+ int_status_32 = (bridge->b_int_status & ~BRIDGE_ISR_INT_MSK);
+ int_status = ((uint64_t)int_status_32) & 0xffffffff;
+ number_bits = PCIBR_ISR_MAX_ERRS_BRIDGE;
+ }
+
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ERROR, pcibr_soft->bs_conn,
+ "pcibr_error_intr_handler: int_status=0x%x\n", int_status));
+
/* int_status is which bits we have to clear;
* err_status is the bits we haven't handled yet.
*/
-
- int_status = bridge->b_int_status & ~BRIDGE_ISR_INT_MSK;
err_status = int_status & ~BRIDGE_ISR_MULTI_ERR;
if (!(int_status & ~BRIDGE_ISR_INT_MSK)) {
@@ -593,11 +847,29 @@
pcibr_pioerr_check(pcibr_soft);
}
+#ifdef BRIDGE_B_DATACORR_WAR
+ if ((pcibr_soft->bs_rev_num == BRIDGE_PART_REV_B) &&
+ (err_status & BRIDGE_IMR_LLP_REC_CBERR)) {
+ if (bridge_rev_b_data_check_disable)
+ printk(KERN_WARNING "\n%s%s: %s%s\n", rev_b_datacorr_warning,
+ pcibr_soft->bs_name, rev_b_datacorr_mesg,
+ rev_b_datacorr_warning);
+ else {
+ ql_bridge_rev_b_war(pcibr_soft->bs_vhdl);
+ PRINT_PANIC( "\n%s%s: %s%s\n", rev_b_datacorr_warning,
+ pcibr_soft->bs_name, rev_b_datacorr_mesg,
+ rev_b_datacorr_warning);
+ }
+
+ err_status &= ~BRIDGE_IMR_LLP_REC_CBERR;
+ }
+#endif /* BRIDGE_B_DATACORR_WAR */
+
if (err_status) {
struct bs_errintr_stat_s *bs_estat = pcibr_soft->bs_errintr_stat;
- for (i = PCIBR_ISR_ERR_START; i < PCIBR_ISR_MAX_ERRS; i++, bs_estat++) {
- if (err_status & (1 << i)) {
+ for (i = PCIBR_ISR_ERR_START; i < number_bits; i++, bs_estat++) {
+ if (err_status & (1ull << i)) {
uint32_t errrate = 0;
uint32_t errcount = 0;
uint32_t errinterval = 0, current_tick = 0;
@@ -606,12 +878,14 @@
bs_estat->bs_errcount_total++;
- current_tick = lbolt;
+ current_tick = jiffies;
errinterval = (current_tick - bs_estat->bs_lasterr_timestamp);
errcount = (bs_estat->bs_errcount_total -
bs_estat->bs_lasterr_snapshot);
- is_llp_tx_retry_intr = (BRIDGE_ISR_LLP_TX_RETRY == (1 << i));
+ /* LLP interrrupt errors are only valid on BUS0 of the PIC */
+ if (pcibr_soft->bs_busnum == 0)
+ is_llp_tx_retry_intr = (BRIDGE_ISR_LLP_TX_RETRY==(1ull << i));
/* Check for the divide by zero condition while
* calculating the error rates.
@@ -698,6 +972,15 @@
bs_estat->bs_errcount_total;
}
}
+ /* PIC BRINGUP WAR (PV# 856155):
+ * Dont disable PCI_X_ARB_ERR interrupts, we need the
+ * interrupt inorder to clear the DEV_BROKE bits in
+ * b_arb register to re-enable the device.
+ */
+ if (IS_PIC_SOFT(pcibr_soft) &&
+ !(err_status & PIC_ISR_PCIX_ARB_ERR) &&
+ PCIBR_WAR_ENABLED(PV856155, pcibr_soft)) {
+
if (bs_estat->bs_errcount_total > PCIBR_ERRINTR_DISABLE_LEVEL) {
/*
* We have seen a fairly large number of errors of
@@ -709,18 +992,26 @@
pcibr_soft->bs_name,
pcibr_isr_errs[i],
bs_estat->bs_errcount_total);
- disable_errintr_mask |= (1 << i);
+ disable_errintr_mask |= (1ull << i);
}
+ } /* PIC: WAR for PV 856155 end-of-if */
}
}
}
if (disable_errintr_mask) {
+ unsigned s;
/*
* Disable some high frequency errors as they
* could eat up too much cpu time.
*/
- bridge->b_int_enable &= ~disable_errintr_mask;
+ s = pcibr_lock(pcibr_soft);
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ bridge->p_int_enable_64 &= (picreg_t)(~disable_errintr_mask);
+ } else {
+ bridge->b_int_enable &= (bridgereg_t)(~disable_errintr_mask);
+ }
+ pcibr_unlock(pcibr_soft, s);
}
/*
* If we leave the PROM cacheable, T5 might
@@ -783,15 +1074,34 @@
if (rv != IOERROR_HANDLED) {
#endif /* EHE_ENABLE */
+ bridge_errors_to_dump |= BRIDGE_ISR_PCIBUS_PIOERR;
+
/* Dump/Log Bridge error interrupt info */
if (err_status & bridge_errors_to_dump) {
- printk("BRIDGE ERR_STATUS 0x%x\n", err_status);
+ printk("BRIDGE ERR_STATUS 0x%lx\n", err_status);
pcibr_error_dump(pcibr_soft);
}
+ /* PIC BRINGUP WAR (PV# 867308):
+ * Make BRIDGE_ISR_LLP_REC_SNERR & BRIDGE_ISR_LLP_REC_CBERR fatal errors
+ * so we know we've hit the problem defined in PV 867308 that we believe
+ * has only been seen in simulation
+ */
+ if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV867308, pcibr_soft) &&
+ (err_status & (BRIDGE_ISR_LLP_REC_SNERR | BRIDGE_ISR_LLP_REC_CBERR))) {
+ printk("BRIDGE ERR_STATUS 0x%x\n", err_status);
+ pcibr_error_dump(pcibr_soft);
+#ifdef LATER
+ machine_error_dump("");
+#endif
+ PRINT_PANIC("PCI Bridge Error interrupt killed the system");
+ }
+
if (err_status & BRIDGE_ISR_ERROR_FATAL) {
+#ifdef LATER
machine_error_dump("");
- cmn_err_tag(14, CE_PANIC, "PCI Bridge Error interrupt killed the system");
+#endif
+ PRINT_PANIC("PCI Bridge Error interrupt killed the system");
/*NOTREACHED */
}
@@ -804,11 +1114,27 @@
* it would cause problems for devices like IOC3 (Lost
* interrupts ?.). So, just cleanup the interrupt, and
* use saved values later..
+ *
+ * PIC doesn't require groups of interrupts to be cleared...
*/
- bridge->b_int_rst_stat = pcibr_errintr_group(int_status);
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ bridge->p_int_rst_stat_64 = (picreg_t)(int_status | BRIDGE_IRR_MULTI_CLR);
+ } else {
+ bridge->b_int_rst_stat = (bridgereg_t)pcibr_errintr_group(int_status);
+ }
+
+ /* PIC BRINGUP WAR (PV# 856155):
+ * On a PCI_X_ARB_ERR error interrupt clear the DEV_BROKE bits from
+ * the b_arb register to re-enable the device.
+ */
+ if (IS_PIC_SOFT(pcibr_soft) &&
+ (err_status & PIC_ISR_PCIX_ARB_ERR) &&
+ PCIBR_WAR_ENABLED(PV856155, pcibr_soft)) {
+ bridge->b_arb |= (0xf << 20);
+ }
/* Zero out bserr_intstat field */
- test_and_set_int((int *) &pcibr_soft->bs_errinfo.bserr_intstat, 0);
+ pcibr_soft->bs_errinfo.bserr_intstat = 0;
}
/*
@@ -832,7 +1158,7 @@
iopaddr_t *offsetp,
pciio_function_t *funcp)
{
- int s, f, w;
+ int s, f = 0, w;
iopaddr_t base;
size_t size;
pciio_piospace_t piosp;
@@ -864,7 +1190,7 @@
return s;
}
- for (s = 0; s < 8; s++) {
+ for (s = pcibr_soft->bs_min_slot; s < PCIBR_NUM_SLOTS(pcibr_soft); ++s) {
int nf = pcibr_soft->bs_slot[s].bss_ninfo;
pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[s].bss_infos;
@@ -874,8 +1200,7 @@
if (!pcibr_info)
continue;
for (w = 0; w < 6; w++) {
- if (pcibr_info->f_window[w].w_space
- == PCIIO_SPACE_NONE) {
+ if (pcibr_info->f_window[w].w_space == PCIIO_SPACE_NONE) {
continue;
}
base = pcibr_info->f_window[w].w_base;
@@ -898,7 +1223,7 @@
* Check if the address was allocated as part of the
* pcibr_piospace_alloc calls.
*/
- for (s = 0; s < 8; s++) {
+ for (s = pcibr_soft->bs_min_slot; s < PCIBR_NUM_SLOTS(pcibr_soft); ++s) {
int nf = pcibr_soft->bs_slot[s].bss_ninfo;
pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[s].bss_infos;
@@ -950,8 +1275,14 @@
ASSERT(error_code & IOECODE_PIO);
error_code = error_code;
- bridge->b_int_rst_stat =
- (BRIDGE_IRR_PCI_GRP_CLR | BRIDGE_IRR_MULTI_CLR);
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ bridge->p_int_rst_stat_64 = BRIDGE_IRR_PCI_GRP_CLR |
+ PIC_PCIX_GRP_CLR |
+ BRIDGE_IRR_MULTI_CLR;
+ } else {
+ bridge->b_int_rst_stat = BRIDGE_IRR_PCI_GRP_CLR | BRIDGE_IRR_MULTI_CLR;
+ }
+
(void) bridge->b_wid_tflush; /* flushbus */
}
@@ -1040,13 +1371,6 @@
* associated with this device.
*/
-#define BEM_ADD_STR(s) printk("%s", (s))
-#define BEM_ADD_VAR(v) printk("\t%20s: 0x%x\n", #v, (v))
-#define BEM_ADD_REG(r) printk("\t%20s: %R\n", #r, (r), r ## _desc)
-
-#define BEM_ADD_NSPC(n,s) printk("\t%20s: %R\n", n, s, space_desc)
-#define BEM_ADD_SPC(s) BEM_ADD_NSPC(#s, s)
-
/* BEM_ADD_IOE doesn't dump the whole ioerror, it just
* decodes the PCI specific portions -- we count on our
* callers to dump the raw IOE data.
@@ -1054,40 +1378,38 @@
#define BEM_ADD_IOE(ioe) \
do { \
if (IOERROR_FIELDVALID(ioe, busspace)) { \
- unsigned spc; \
- unsigned win; \
+ iopaddr_t spc; \
+ iopaddr_t win; \
+ short widdev; \
+ iopaddr_t busaddr; \
\
- spc = IOERROR_GETVALUE(ioe, busspace); \
+ IOERROR_GETVALUE(spc, ioe, busspace); \
win = spc - PCIIO_SPACE_WIN(0); \
+ IOERROR_GETVALUE(busaddr, ioe, busaddr); \
+ IOERROR_GETVALUE(widdev, ioe, widgetdev); \
\
switch (spc) { \
case PCIIO_SPACE_CFG: \
- printk( \
- "\tPCI Slot %d Func %d CFG space Offset 0x%x\n", \
- pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe, widgetdev)), \
- pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe, widgetdev)), \
- IOERROR_GETVALUE(ioe, busaddr)); \
+ printk("\tPCI Slot %d Func %d CFG space Offset 0x%lx\n",\
+ pciio_widgetdev_slot_get(widdev), \
+ pciio_widgetdev_func_get(widdev), \
+ busaddr); \
break; \
case PCIIO_SPACE_IO: \
- printk( \
- "\tPCI I/O space Offset 0x%x\n", \
- IOERROR_GETVALUE(ioe, busaddr)); \
+ printk("\tPCI I/O space Offset 0x%lx\n", busaddr); \
break; \
case PCIIO_SPACE_MEM: \
case PCIIO_SPACE_MEM32: \
case PCIIO_SPACE_MEM64: \
- printk( \
- "\tPCI MEM space Offset 0x%x\n", \
- IOERROR_GETVALUE(ioe, busaddr)); \
+ printk("\tPCI MEM space Offset 0x%lx\n", busaddr); \
break; \
default: \
if (win < 6) { \
- printk( \
- "\tPCI Slot %d Func %d Window %d Offset 0x%x\n",\
- pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe, widgetdev)), \
- pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe, widgetdev)), \
- win, \
- IOERROR_GETVALUE(ioe, busaddr)); \
+ printk("\tPCI Slot %d Func %d Window %ld Offset 0x%lx\n",\
+ pciio_widgetdev_slot_get(widdev), \
+ pciio_widgetdev_func_get(widdev), \
+ win, \
+ busaddr); \
} \
break; \
} \
@@ -1129,34 +1451,38 @@
* and need to construct the slot/space/offset.
*/
- bad_xaddr = IOERROR_GETVALUE(ioe, xtalkaddr);
+ IOERROR_GETVALUE(bad_xaddr, ioe, xtalkaddr);
+
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn,
+ "pcibr_pioerror: pcibr_soft=0x%x, bad_xaddr=0x%x\n",
+ pcibr_soft, bad_xaddr));
slot = PCIIO_SLOT_NONE;
func = PCIIO_FUNC_NONE;
raw_space = PCIIO_SPACE_NONE;
raw_paddr = 0;
- if ((bad_xaddr >= BRIDGE_TYPE0_CFG_DEV0) &&
- (bad_xaddr < BRIDGE_TYPE1_CFG)) {
- raw_paddr = bad_xaddr - BRIDGE_TYPE0_CFG_DEV0;
+ if ((bad_xaddr >= PCIBR_BUS_TYPE0_CFG_DEV0(pcibr_soft)) &&
+ (bad_xaddr < PCIBR_TYPE1_CFG(pcibr_soft))) {
+ raw_paddr = bad_xaddr - PCIBR_BUS_TYPE0_CFG_DEV0(pcibr_soft);
slot = raw_paddr / BRIDGE_TYPE0_CFG_SLOT_OFF;
raw_paddr = raw_paddr % BRIDGE_TYPE0_CFG_SLOT_OFF;
raw_space = PCIIO_SPACE_CFG;
}
- if ((bad_xaddr >= BRIDGE_TYPE1_CFG) &&
- (bad_xaddr < (BRIDGE_TYPE1_CFG + 0x1000))) {
+ if ((bad_xaddr >= PCIBR_TYPE1_CFG(pcibr_soft)) &&
+ (bad_xaddr < (PCIBR_TYPE1_CFG(pcibr_soft) + 0x1000))) {
/* Type 1 config space:
* slot and function numbers not known.
* Perhaps we can read them back?
*/
- raw_paddr = bad_xaddr - BRIDGE_TYPE1_CFG;
+ raw_paddr = bad_xaddr - PCIBR_TYPE1_CFG(pcibr_soft);
raw_space = PCIIO_SPACE_CFG;
}
- if ((bad_xaddr >= BRIDGE_DEVIO0) &&
- (bad_xaddr < BRIDGE_DEVIO(BRIDGE_DEV_CNT))) {
+ if ((bad_xaddr >= PCIBR_BRIDGE_DEVIO0(pcibr_soft)) &&
+ (bad_xaddr < PCIBR_BRIDGE_DEVIO(pcibr_soft, BRIDGE_DEV_CNT))) {
int x;
- raw_paddr = bad_xaddr - BRIDGE_DEVIO0;
+ raw_paddr = bad_xaddr - PCIBR_BRIDGE_DEVIO0(pcibr_soft);
x = raw_paddr / BRIDGE_DEVIO_OFF;
raw_paddr %= BRIDGE_DEVIO_OFF;
/* first two devio windows are double-sized */
@@ -1223,7 +1549,9 @@
* going on (no guessing).
*/
- for (cs = 0; (cs < 8) && (slot == PCIIO_SLOT_NONE); cs++) {
+ for (cs = pcibr_soft->bs_min_slot;
+ (cs < PCIBR_NUM_SLOTS(pcibr_soft)) &&
+ (slot == PCIIO_SLOT_NONE); cs++) {
int nf = pcibr_soft->bs_slot[cs].bss_ninfo;
pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[cs].bss_infos;
@@ -1283,7 +1611,8 @@
* strict count, the excess counts are not a
* problem.
*/
- for (cs = 0; cs < 8; ++cs) {
+ for (cs = pcibr_soft->bs_min_slot;
+ cs < PCIBR_NUM_SLOTS(pcibr_soft); ++cs) {
int nf = pcibr_soft->bs_slot[cs].bss_ninfo;
pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[cs].bss_infos;
@@ -1313,7 +1642,7 @@
wx = PCIIO_SPACE_MEM;
wl = wb + ws;
if ((wx == raw_space) && (raw_paddr >= wb) && (raw_paddr < wl)) {
- atomicAddInt(map->bp_toc, 1);
+ atomic_inc(&map->bp_toc[0]);
if (slot == PCIIO_SLOT_NONE) {
slot = cs;
space = map->bp_space;
@@ -1325,15 +1654,21 @@
}
}
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn,
+ "pcibr_pioerror: offset=0x%x, slot=0x%x, func=0x%x\n",
+ offset, slot, func));
+
if (space != PCIIO_SPACE_NONE) {
- if (slot != PCIIO_SLOT_NONE)
- if (func != PCIIO_FUNC_NONE)
+ if (slot != PCIIO_SLOT_NONE) {
+ if (func != PCIIO_FUNC_NONE) {
IOERROR_SETVALUE(ioe, widgetdev,
pciio_widgetdev_create(slot,func));
- else
+ }
+ else {
IOERROR_SETVALUE(ioe, widgetdev,
pciio_widgetdev_create(slot,0));
-
+ }
+ }
IOERROR_SETVALUE(ioe, busspace, space);
IOERROR_SETVALUE(ioe, busaddr, offset);
}
@@ -1360,7 +1695,7 @@
if (space == PCIIO_SPACE_NONE) {
printk("XIO Bus Error at %s\n"
- "\taccess to XIO bus offset 0x%x\n"
+ "\taccess to XIO bus offset 0x%lx\n"
"\tdoes not correspond to any PCI address\n",
pcibr_soft->bs_name, bad_xaddr);
@@ -1434,17 +1769,21 @@
*/
BEM_ADD_STR("Raw info from Bridge/PCI layer:\n");
- if (bridge->b_int_status & BRIDGE_ISR_PCIBUS_PIOERR)
- pcibr_error_dump(pcibr_soft);
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ if (bridge->p_int_status_64 & (picreg_t)BRIDGE_ISR_PCIBUS_PIOERR)
+ pcibr_error_dump(pcibr_soft);
+ } else {
+ if (bridge->b_int_status & (bridgereg_t)BRIDGE_ISR_PCIBUS_PIOERR)
+ pcibr_error_dump(pcibr_soft);
+ }
BEM_ADD_SPC(raw_space);
BEM_ADD_VAR(raw_paddr);
if (IOERROR_FIELDVALID(ioe, widgetdev)) {
-
- slot = pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe,
- widgetdev));
- func = pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe,
- widgetdev));
- if (slot < 8) {
+ short widdev;
+ IOERROR_GETVALUE(widdev, ioe, widgetdev);
+ slot = pciio_widgetdev_slot_get(widdev);
+ func = pciio_widgetdev_func_get(widdev);
+ if (slot < PCIBR_NUM_SLOTS(pcibr_soft)) {
bridgereg_t device = bridge->b_device[slot].reg;
BEM_ADD_VAR(slot);
@@ -1472,11 +1811,12 @@
* Need a way to ensure we don't inadvertently clear some
* other errors.
*/
- if (IOERROR_FIELDVALID(ioe, widgetdev))
- pcibr_device_disable(pcibr_soft,
- pciio_widgetdev_slot_get(
- IOERROR_GETVALUE(ioe, widgetdev)));
-
+ if (IOERROR_FIELDVALID(ioe, widgetdev)) {
+ short widdev;
+ IOERROR_GETVALUE(widdev, ioe, widgetdev);
+ pcibr_device_disable(pcibr_soft,
+ pciio_widgetdev_slot_get(widdev));
+ }
if (mode == MODE_DEVUSERERROR)
pcibr_error_cleanup(pcibr_soft, error_code);
}
@@ -1490,8 +1830,6 @@
* and try to invoke the appropriate bus service to handle this.
*/
-#define BRIDGE_DMA_READ_ERROR (BRIDGE_ISR_RESP_XTLK_ERR|BRIDGE_ISR_XREAD_REQ_TIMEOUT)
-
int
pcibr_dmard_error(
pcibr_soft_t pcibr_soft,
@@ -1511,7 +1849,11 @@
* Look up the address, in the bridge error registers, and
* take appropriate action
*/
- ASSERT(IOERROR_GETVALUE(ioe, widgetnum) == pcibr_soft->bs_xid);
+ {
+ short tmp;
+ IOERROR_GETVALUE(tmp, ioe, widgetnum);
+ ASSERT(tmp == pcibr_soft->bs_xid);
+ }
ASSERT(bridge);
/*
@@ -1540,10 +1882,11 @@
*/
retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe);
- if (retval != IOERROR_HANDLED)
- pcibr_device_disable(pcibr_soft,
- pciio_widgetdev_slot_get(
- IOERROR_GETVALUE(ioe,widgetdev)));
+ if (retval != IOERROR_HANDLED) {
+ short tmp;
+ IOERROR_GETVALUE(tmp, ioe, widgetdev);
+ pcibr_device_disable(pcibr_soft, pciio_widgetdev_slot_get(tmp));
+ }
/*
* Re-enable bridge to interrupt on BRIDGE_IRR_RESP_BUF_GRP_CLR
@@ -1609,10 +1952,10 @@
retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe);
if (retval != IOERROR_HANDLED) {
- pcibr_device_disable(pcibr_soft,
- pciio_widgetdev_slot_get(
- IOERROR_GETVALUE(ioe, widgetdev)));
+ short tmp;
+ IOERROR_GETVALUE(tmp, ioe, widgetdev);
+ pcibr_device_disable(pcibr_soft, pciio_widgetdev_slot_get(tmp));
}
return retval;
}
@@ -1646,6 +1989,10 @@
pcibr_soft = (pcibr_soft_t) einfo;
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn,
+ "pcibr_error_handler: pcibr_soft=0x%x, error_code=0x%x\n",
+ pcibr_soft, error_code));
+
#ifdef EHE_ENABLE
xconn_vhdl = pcibr_soft->bs_conn;
pcibr_vhdl = pcibr_soft->bs_vhdl;
@@ -1664,7 +2011,7 @@
#endif /* EHE_ENABLE */
#if DEBUG && ERROR_DEBUG
- printk("%s: pcibr_error_handler\n", pcibr_soft->bs_name);
+ printk( "%s: pcibr_error_handler\n", pcibr_soft->bs_name);
#endif
ASSERT(pcibr_soft != NULL);
@@ -1704,6 +2051,159 @@
}
/*
+ * PIC has 2 busses under a single widget so pcibr_attach2 registers this
+ * wrapper function rather than pcibr_error_handler() for PIC. It's upto
+ * this wrapper to call pcibr_error_handler() with the correct pcibr_soft
+ * struct (ie. the pcibr_soft struct for the bus that saw the error).
+ *
+ * NOTE: this wrapper function is only registered for PIC ASICs and will
+ * only be called for a PIC
+ */
+int
+pcibr_error_handler_wrapper(
+ error_handler_arg_t einfo,
+ int error_code,
+ ioerror_mode_t mode,
+ ioerror_t *ioe)
+{
+ pcibr_soft_t pcibr_soft = (pcibr_soft_t) einfo;
+ int pio_retval = -1;
+ int dma_retval = -1;
+
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn,
+ "pcibr_error_handler_wrapper: pcibr_soft=0x%x, "
+ "error_code=0x%x\n", pcibr_soft, error_code));
+
+ /*
+ * It is possible that both a IOECODE_PIO and a IOECODE_DMA, and both
+ * IOECODE_READ and IOECODE_WRITE could be set in error_code so we must
+ * process all. Since we are a wrapper for pcibr_error_handler(), and
+ * will be calling it several times within this routine, we turn off the
+ * error_code bits we don't want it to be processing during that call.
+ */
+ /*
+ * If the error was a result of a PIO, we tell what bus on the PIC saw
+ * the error from the PIO address.
+ */
+
+#if 0
+ if (mode == MODE_DEVPROBE)
+ pio_retval = IOERROR_HANDLED;
+ else {
+#endif
+ if (error_code & IOECODE_PIO) {
+ iopaddr_t bad_xaddr;
+ /*
+ * PIC bus0 PIO space 0x000000 - 0x7fffff or 0x40000000 - 0xbfffffff
+ * bus1 PIO space 0x800000 - 0xffffff or 0xc0000000 - 0x13fffffff
+ */
+ IOERROR_GETVALUE(bad_xaddr, ioe, xtalkaddr);
+ if ((bad_xaddr <= 0x7fffff) ||
+ ((bad_xaddr >= 0x40000000) && (bad_xaddr <= 0xbfffffff))) {
+ /* bus 0 saw the error */
+ pio_retval = pcibr_error_handler((error_handler_arg_t)pcibr_soft,
+ (error_code & ~IOECODE_DMA), mode, ioe);
+ } else if (((bad_xaddr >= 0x800000) && (bad_xaddr <= 0xffffff)) ||
+ ((bad_xaddr >= 0xc0000000) && (bad_xaddr <= 0x13fffffff))) {
+ /* bus 1 saw the error */
+ pcibr_soft = pcibr_soft->bs_peers_soft;
+ if (!pcibr_soft) {
+#if DEBUG
+ printk(KERN_WARNING "pcibr_error_handler: "
+ "bs_peers_soft==NULL. bad_xaddr= 0x%x mode= 0x%x\n",
+ bad_xaddr, mode);
+#endif
+ pio_retval = IOERROR_HANDLED;
+ } else
+ pio_retval= pcibr_error_handler((error_handler_arg_t)pcibr_soft,
+ (error_code & ~IOECODE_DMA), mode, ioe);
+ } else {
+ printk(KERN_WARNING "pcibr_error_handler_wrapper(): IOECODE_PIO: "
+ "saw an invalid pio address: 0x%lx\n", bad_xaddr);
+ pio_retval = IOERROR_UNHANDLED;
+ }
+ }
+#if 0
+ } /* MODE_DEVPROBE */
+#endif
+
+ /*
+ * If the error was a result of a DMA Write, we tell what bus on the PIC
+ * saw the error by looking at tnum.
+ */
+ if ((error_code & IOECODE_DMA) && (error_code & IOECODE_WRITE)) {
+ short tmp;
+ /*
+ * For DMA writes [X]Bridge encodes the TNUM field of a Xtalk
+ * packet like this:
+ * bits value
+ * 4:3 10b
+ * 2:0 device number
+ *
+ * BUT PIC needs the bus number so it does this:
+ * bits value
+ * 4:3 10b
+ * 2 busnumber
+ * 1:0 device number
+ *
+ * Pull out the bus number from `tnum' and reset the `widgetdev'
+ * since when hubiio_crb_error_handler() set `widgetdev' it had
+ * no idea if it was a PIC or a BRIDGE ASIC so it set it based
+ * off bits 2:0
+ */
+ IOERROR_GETVALUE(tmp, ioe, tnum);
+ IOERROR_SETVALUE(ioe, widgetdev, (tmp & 0x3));
+ if ((tmp & 0x4) == 0) {
+ /* bus 0 saw the error. */
+ dma_retval = pcibr_error_handler((error_handler_arg_t)pcibr_soft,
+ (error_code & ~(IOECODE_PIO|IOECODE_READ)), mode, ioe);
+ } else {
+ /* bus 1 saw the error */
+ pcibr_soft = pcibr_soft->bs_peers_soft;
+ dma_retval = pcibr_error_handler((error_handler_arg_t)pcibr_soft,
+ (error_code & ~(IOECODE_PIO|IOECODE_READ)), mode, ioe);
+ }
+ }
+
+ /*
+ * If the error was a result of a DMA READ, XXX ???
+ */
+ if ((error_code & IOECODE_DMA) && (error_code & IOECODE_READ)) {
+ /*
+ * A DMA Read error will result in a BRIDGE_ISR_RESP_XTLK_ERR
+ * or BRIDGE_ISR_BAD_XRESP_PKT bridge error interrupt which
+ * are fatal interrupts (ie. BRIDGE_ISR_ERROR_FATAL) causing
+ * pcibr_error_intr_handler() to panic the system. So is the
+ * error handler even going to get called??? It appears that
+ * the pcibr_dmard_error() attempts to clear the interrupts
+ * so pcibr_error_intr_handler() won't see them, but there
+ * appears to be nothing to prevent pcibr_error_intr_handler()
+ * from running before pcibr_dmard_error() has a chance to
+ * clear the interrupt.
+ *
+ * Since we'll be panicing anyways, don't bother handling the
+ * error for now until we can fix this race condition mentioned
+ * above.
+ */
+ dma_retval = IOERROR_UNHANDLED;
+ }
+
+ /* XXX: pcibr_error_handler() should probably do the same thing, it over-
+ * write it's return value as it processes the different "error_code"s.
+ */
+ if ((pio_retval == -1) && (dma_retval == -1)) {
+ return IOERROR_BADERRORCODE;
+ } else if (dma_retval != IOERROR_HANDLED) {
+ return dma_retval;
+ } else if (pio_retval != IOERROR_HANDLED) {
+ return pio_retval;
+ } else {
+ return IOERROR_HANDLED;
+ }
+}
+
+
+/*
* Reenable a device after handling the error.
* This is called by the lower layers when they wish to be reenabled
* after an error.
@@ -1715,7 +2215,7 @@
pcibr_error_devenable(devfs_handle_t pconn_vhdl, int error_code)
{
pciio_info_t pciio_info = pciio_info_get(pconn_vhdl);
- pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+ pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
ASSERT(error_code & IOECODE_PIO);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)