📄 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-2002 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/eeprom.h>#include <asm/sn/io.h>#include <asm/sn/sn_private.h>#ifdef __ia64#define rmallocmap atemapalloc#define rmfreemap atemapfree#define rmfree atefree#define rmalloc atealloc#endifextern 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#ifdef DEBUG#ifdef ERROR_DEBUGbridgereg_t bridge_errors_to_dump = ~BRIDGE_ISR_INT_MSK;#elsebridgereg_t bridge_errors_to_dump = BRIDGE_ISR_ERROR_DUMP;#endif#elsebridgereg_t bridge_errors_to_dump = BRIDGE_ISR_ERROR_FATAL | BRIDGE_ISR_PCIBUS_PIOERR;#endif#if defined (PCIBR_LLP_CONTROL_WAR)int pcibr_llp_control_war_cnt;#endif /* PCIBR_LLP_CONTROL_WAR *//* FIXME: can these arrays be local ? */#ifdef LATERstruct 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}};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 }struct reg_desc bridge_int_status_desc[] ={ F(31, "MULTI_ERR"), F(30, "PMU_ESIZE_EFAULT"), F(29, "UNEXPECTED_RESP"), F(28, "BAD_XRESP_PACKET"), F(27, "BAD_XREQ_PACKET"), F(26, "RESP_XTALK_ERROR"), F(25, "REQ_XTALK_ERROR"), F(24, "INVALID_ADDRESS"), F(23, "UNSUPPORTED_XOP"), F(22, "XREQ_FIFO_OFLOW"), F(21, "LLP_REC_SNERROR"), F(20, "LLP_REC_CBERROR"), F(19, "LLP_RCTY"), F(18, "LLP_TX_RETRY"), F(17, "LLP_TCTY"), F(16, "SSRAM_PERR"), F(15, "PCI_ABORT"), F(14, "PCI_PARITY"), F(13, "PCI_SERR"), F(12, "PCI_PERR"), F(11, "PCI_MASTER_TOUT"), F(10, "PCI_RETRY_CNT"), F(9, "XREAD_REQ_TOUT"), F(8, "GIO_BENABLE_ERR"), F(7, "INT7"), F(6, "INT6"), F(5, "INT5"), F(4, "INT4"), F(3, "INT3"), F(2, "INT2"), F(1, "INT1"), F(0, "INT0"), {0}};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}};struct reg_desc space_desc[] ={ {0xFF, 0, "space", 0, space_v}, {0}};#define device_desc device_bitsstruct 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 /* LATER */voidprint_bridge_errcmd(uint32_t cmdword, char *errtype){ printk( "\t Bridge %s Error Command Word Register %R\n", errtype, cmdword, xio_cmd_bits);}char *pcibr_isr_errs[] ={ "", "", "", "", "", "", "", "", "08: GIO non-contiguous byte enable in crosstalk packet", "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", "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",};#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)/* * display memory directory state */voidpcibr_show_dir_state(paddr_t paddr, char *prefix){ 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); printf("%saddr 0x%x: state 0x%x owner 0x%x (%s)\n", prefix, paddr, state, vec_ptr, dir_state_str[state]);}/* * Dump relevant error information for Bridge error interrupts. *//*ARGSUSED */voidpcibr_error_dump(pcibr_soft_t pcibr_soft){ bridge_t *bridge = pcibr_soft->bs_base; bridgereg_t int_status; bridgereg_t mult_int; int bit; int i; char *reg_desc; paddr_t addr; 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) { return; } printk(KERN_ALERT "PCI BRIDGE ERROR: int_status is 0x%X for %s\n" " Dumping relevant %sBridge registers for each bit set...\n", int_status, pcibr_soft->bs_name, (is_xbridge(bridge) ? "X" : "")); for (i = PCIBR_ISR_ERR_START; i < PCIBR_ISR_MAX_ERRS; i++) { bit = 1 << i; /* * A number of int_status bits are only defined for Bridge. * Ignore them in the case of an XBridge. */ if (is_xbridge(bridge) && ((bit == BRIDGE_ISR_MULTI_ERR) || (bit == BRIDGE_ISR_SSRAM_PERR) || (bit == BRIDGE_ISR_GIO_B_ENBL_ERR))) { continue; } if (int_status & bit) { 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)) 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: /* UNEXPECTED_RESP */ print_bridge_errcmd(bridge->b_wid_aux_err, "Aux"); break; 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 */ 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); 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", (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 */ 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", (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; } } } 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]); } }}#define PCIBR_ERRINTR_GROUP(error) \ (( error & (BRIDGE_IRR_PCI_GRP|BRIDGE_IRR_GIO_GRP)uint32_tpcibr_errintr_group(uint32_t error){ uint32_t group = BRIDGE_IRR_MULTI_CLR; if (error & BRIDGE_IRR_PCI_GRP) group |= BRIDGE_IRR_PCI_GRP_CLR; if (error & BRIDGE_IRR_SSRAM_GRP) group |= BRIDGE_IRR_SSRAM_GRP_CLR; if (error & BRIDGE_IRR_LLP_GRP) group |= BRIDGE_IRR_LLP_GRP_CLR; if (error & BRIDGE_IRR_REQ_DSP_GRP) group |= BRIDGE_IRR_REQ_DSP_GRP_CLR; if (error & BRIDGE_IRR_RESP_BUF_GRP) group |= BRIDGE_IRR_RESP_BUF_GRP_CLR; if (error & BRIDGE_IRR_CRP_GRP) group |= BRIDGE_IRR_CRP_GRP_CLR; return group;}/* pcibr_pioerr_check(): * Check to see if this pcibr has a PCI PIO * TIMEOUT error; if so, bump the timeout-count * on any piomaps that could cover the address. */static voidpcibr_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -