📄 pcibr_error.c
字号:
/* * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */#include <linux/types.h>#include <linux/slab.h>#include <linux/module.h>#include <asm/sn/sgi.h>#include <asm/sn/sn_cpuid.h>#include <asm/sn/addrs.h>#include <asm/sn/arch.h>#include <asm/sn/iograph.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/labelcl.h>#include <asm/sn/xtalk/xwidget.h>#include <asm/sn/pci/bridge.h>#include <asm/sn/pci/pciio.h>#include <asm/sn/pci/pcibr.h>#include <asm/sn/pci/pcibr_private.h>#include <asm/sn/pci/pci_defs.h>#include <asm/sn/prio.h>#include <asm/sn/xtalk/xbow.h>#include <asm/sn/ioc3.h>#include <asm/sn/io.h>#include <asm/sn/sn_private.h>extern int hubii_check_widget_disabled(nasid_t, int);/* ===================================================================== * ERROR HANDLING */#ifdef DEBUG#ifdef ERROR_DEBUG#define BRIDGE_PIOERR_TIMEOUT 100 /* Timeout with ERROR_DEBUG defined */#else#define BRIDGE_PIOERR_TIMEOUT 40 /* Timeout in debug mode */#endif#else#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_DEBUGuint64_t bridge_errors_to_dump = ~BRIDGE_ISR_INT_MSK;#elseuint64_t bridge_errors_to_dump = BRIDGE_ISR_ERROR_DUMP;#endif#elseuint64_t bridge_errors_to_dump = BRIDGE_ISR_ERROR_FATAL | BRIDGE_ISR_PCIBUS_PIOERR;#endifint pcibr_llp_control_war_cnt; /* PCIBR_LLP_CONTROL_WAR */static struct reg_values xio_cmd_pactyp[] ={ {0x0, "RdReq"}, {0x1, "RdResp"}, {0x2, "WrReqWithResp"}, {0x3, "WrResp"}, {0x4, "WrReqNoResp"}, {0x5, "Reserved(5)"}, {0x6, "FetchAndOp"}, {0x7, "Reserved(7)"}, {0x8, "StoreAndOp"}, {0x9, "Reserved(9)"}, {0xa, "Reserved(a)"}, {0xb, "Reserved(b)"}, {0xc, "Reserved(c)"}, {0xd, "Reserved(d)"}, {0xe, "SpecialReq"}, {0xf, "SpecialResp"}, {0}};static struct reg_desc xio_cmd_bits[] ={ {WIDGET_DIDN, -28, "DIDN", "%x"}, {WIDGET_SIDN, -24, "SIDN", "%x"}, {WIDGET_PACTYP, -20, "PACTYP", 0, xio_cmd_pactyp}, {WIDGET_TNUM, -15, "TNUM", "%x"}, {WIDGET_COHERENT, 0, "COHERENT"}, {WIDGET_DS, 0, "DS"}, {WIDGET_GBR, 0, "GBR"}, {WIDGET_VBPM, 0, "VBPM"}, {WIDGET_ERROR, 0, "ERROR"}, {WIDGET_BARRIER, 0, "BARRIER"}, {0}};#define F(s,n) { 1l<<(s),-(s), n }#if defined(FORCE_ERRORS)static struct reg_values space_v[] ={ {PCIIO_SPACE_NONE, "none"}, {PCIIO_SPACE_ROM, "ROM"}, {PCIIO_SPACE_IO, "I/O"}, {PCIIO_SPACE_MEM, "MEM"}, {PCIIO_SPACE_MEM32, "MEM(32)"}, {PCIIO_SPACE_MEM64, "MEM(64)"}, {PCIIO_SPACE_CFG, "CFG"}, {PCIIO_SPACE_WIN(0), "WIN(0)"}, {PCIIO_SPACE_WIN(1), "WIN(1)"}, {PCIIO_SPACE_WIN(2), "WIN(2)"}, {PCIIO_SPACE_WIN(3), "WIN(3)"}, {PCIIO_SPACE_WIN(4), "WIN(4)"}, {PCIIO_SPACE_WIN(5), "WIN(5)"}, {PCIIO_SPACE_BAD, "BAD"}, {0}};static struct reg_desc space_desc[] ={ {0xFF, 0, "space", 0, space_v}, {0}};#define device_desc device_bitsstatic struct reg_desc device_bits[] ={ {BRIDGE_DEV_ERR_LOCK_EN, 0, "ERR_LOCK_EN"}, {BRIDGE_DEV_PAGE_CHK_DIS, 0, "PAGE_CHK_DIS"}, {BRIDGE_DEV_FORCE_PCI_PAR, 0, "FORCE_PCI_PAR"}, {BRIDGE_DEV_VIRTUAL_EN, 0, "VIRTUAL_EN"}, {BRIDGE_DEV_PMU_WRGA_EN, 0, "PMU_WRGA_EN"}, {BRIDGE_DEV_DIR_WRGA_EN, 0, "DIR_WRGA_EN"}, {BRIDGE_DEV_DEV_SIZE, 0, "DEV_SIZE"}, {BRIDGE_DEV_RT, 0, "RT"}, {BRIDGE_DEV_SWAP_PMU, 0, "SWAP_PMU"}, {BRIDGE_DEV_SWAP_DIR, 0, "SWAP_DIR"}, {BRIDGE_DEV_PREF, 0, "PREF"}, {BRIDGE_DEV_PRECISE, 0, "PRECISE"}, {BRIDGE_DEV_COH, 0, "COH"}, {BRIDGE_DEV_BARRIER, 0, "BARRIER"}, {BRIDGE_DEV_GBR, 0, "GBR"}, {BRIDGE_DEV_DEV_SWAP, 0, "DEV_SWAP"}, {BRIDGE_DEV_DEV_IO_MEM, 0, "DEV_IO_MEM"}, {BRIDGE_DEV_OFF_MASK, BRIDGE_DEV_OFF_ADDR_SHFT, "DEV_OFF", "%x"}, {0}};#endif /* FORCE_ERRORS */static voidprint_bridge_errcmd(uint32_t cmdword, char *errtype){ printk("\t Bridge %s Error Command Word Register ", errtype); print_register(cmdword, xio_cmd_bits);}static char *pcibr_isr_errs[] ={ "", "", "", "", "", "", "", "", "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", "12: PCI device reported parity error", "13: PCI Address/Cmd parity error ", "14: PCI Bridge detected parity error", "15: PCI abort condition", "16: SSRAM parity error", /* BRIDGE ONLY */ "17: LLP Transmitter Retry count wrapped", "18: LLP Transmitter side required Retry", "19: LLP Receiver retry count wrapped", "20: LLP Receiver check bit error", "21: LLP Receiver sequence number error", "22: Request packet overflow", "23: Request operation not supported by bridge", "24: Request packet has invalid address for bridge widget", "25: Incoming request xtalk command word error bit set or invalid sideband", "26: Incoming response xtalk command word error bit set or invalid sideband", "27: Framing error, request cmd data size does not match actual", "28: Framing error, response cmd data size does not match actual", "29: Unexpected response arrived", "30: PMU Access Fault", "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%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)/* * display memory directory state */static voidpcibr_show_dir_state(paddr_t paddr, char *prefix){#ifdef LATER int state; uint64_t vec_ptr; hubreg_t elo; extern char *dir_state_str[]; extern void get_dir_ent(paddr_t, int *, uint64_t *, hubreg_t *); get_dir_ent(paddr, &state, &vec_ptr, &elo); printk("%saddr 0x%lx: state 0x%x owner 0x%lx (%s)\n", prefix, paddr, state, vec_ptr, dir_state_str[state]);#endif}/* * Dump relevant error information for Bridge error interrupts. *//*ARGSUSED */voidpcibr_error_dump(pcibr_soft_t pcibr_soft){ bridge_t *bridge = pcibr_soft->bs_base; 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)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; } if (!int_status) { /* No error bits set */ return; } /* Check if dumping the same error information multiple times */ 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%lx for %s\n" " Dumping relevant %s registers for each bit set...\n", int_status, pcibr_soft->bs_name, (IS_PIC_SOFT(pcibr_soft) ? "PIC" : (IS_BRIDGE_SOFT(pcibr_soft) ? "BRIDGE" : "XBRIDGE"))); 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 or PIC. */ 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; } if (int_status & bit) { printk("\t%s\n", pcibr_isr_errs[i]); switch (bit) { 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 */ 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, bridge->b_ram_perr_or_map_fault); break; case BRIDGE_ISR_UNEXP_RESP: /* bit29 UNEXPECTED_RESP */ print_bridge_errcmd(bridge->b_wid_aux_err, "Aux "); /* 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; 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: /* 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_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(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -