pcibr_error.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,874 行 · 第 1/4 页
C
1,874 行
/* * 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/interrupt.h>#include <asm/sn/sgi.h>#include <asm/sn/addrs.h>#include <asm/sn/iograph.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>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#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_pioerr_dump = 1; /* always dump pio errors *//* * register values * map between numeric values and symbolic values */struct reg_values { unsigned long long rv_value; char *rv_name;};/* * register descriptors are used for formatted prints of register values * rd_mask and rd_shift must be defined, other entries may be null */struct reg_desc { unsigned long long rd_mask; /* mask to extract field */ int rd_shift; /* shift for extracted value, - >>, + << */ char *rd_name; /* field name */ char *rd_format; /* format to print field */ struct reg_values *rd_values; /* symbolic names of values */};/* Crosstalk Packet Types */static struct reg_values xtalk_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 xtalk_cmd_bits[] ={ {WIDGET_DIDN, -28, "DIDN", "%x"}, {WIDGET_SIDN, -24, "SIDN", "%x"}, {WIDGET_PACTYP, -20, "PACTYP", 0, xtalk_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 }char *pci_space[] = {"NONE", "ROM", "IO", "", "MEM", "MEM32", "MEM64", "CFG", "WIN0", "WIN1", "WIN2", "WIN3", "WIN4", "WIN5", "", "BAD"};static char *pcibr_isr_errs[] ={ "", "", "", "", "", "", "", "", "08: Reserved Bit 08", "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: Reserved Bit 16", "17: LLP Transmitter Retry count wrapped", /* PIC ONLY */ "18: LLP Transmitter side required Retry", /* PIC ONLY */ "19: LLP Receiver retry count wrapped", /* PIC ONLY */ "20: LLP Receiver check bit error", /* PIC ONLY */ "21: LLP Receiver sequence number error", /* PIC ONLY */ "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: Reserved Bit 31", "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",};/* * print_register() allows formatted printing of bit fields. individual * bit fields are described by a struct reg_desc, multiple bit fields within * a single word can be described by multiple reg_desc structures. * %r outputs a string of the format "<bit field descriptions>" * %R outputs a string of the format "0x%x<bit field descriptions>" * * The fields in a reg_desc are: * unsigned long long rd_mask; An appropriate mask to isolate the bit field * within a word, and'ed with val * * int rd_shift; A shift amount to be done to the isolated * bit field. done before printing the isolate * bit field with rd_format and before searching * for symbolic value names in rd_values * * char *rd_name; If non-null, a bit field name to label any * out from rd_format or searching rd_values. * if neither rd_format or rd_values is non-null * rd_name is printed only if the isolated * bit field is non-null. * * char *rd_format; If non-null, the shifted bit field value * is printed using this format. * * struct reg_values *rd_values; If non-null, a pointer to a table * matching numeric values with symbolic names. * rd_values are searched and the symbolic * value is printed if a match is found, if no * match is found "???" is printed. * */static voidprint_register(unsigned long long reg, struct reg_desc *addr){ register struct reg_desc *rd; register struct reg_values *rv; unsigned long long field; int any; printk("<"); any = 0; for (rd = addr; rd->rd_mask; rd++) { field = reg & rd->rd_mask; field = (rd->rd_shift > 0) ? field << rd->rd_shift : field >> -rd->rd_shift; if (any && (rd->rd_format || rd->rd_values || (rd->rd_name && field))) printk(","); if (rd->rd_name) { if (rd->rd_format || rd->rd_values || field) { printk("%s", rd->rd_name); any = 1; } if (rd->rd_format || rd->rd_values) { printk("="); any = 1; } } /* You can have any format so long as it is %x */ if (rd->rd_format) { printk("%llx", field); any = 1; if (rd->rd_values) printk(":"); } if (rd->rd_values) { any = 1; for (rv = rd->rd_values; rv->rv_name; rv++) { if (field == rv->rv_value) { printk("%s", rv->rv_name); break; } } if (rv->rv_name == NULL) printk("???"); } } printk(">\n");}/* * display memory directory state */static voidpcibr_show_dir_state(paddr_t paddr, char *prefix){#ifdef PCIBR_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); printf("%saddr 0x%lx: state 0x%x owner 0x%lx (%s)\n", prefix, (uint64_t)paddr, state, (uint64_t)vec_ptr, dir_state_str[state]);#endif /* PCIBR_LATER */}voidprint_bridge_errcmd(pcibr_soft_t pcibr_soft, uint32_t cmdword, char *errtype){ printk( "\t Bridge %sError Command Word Register ", errtype); print_register(cmdword, xtalk_cmd_bits);}/* * Dump relevant error information for Bridge error interrupts. *//*ARGSUSED */voidpcibr_error_dump(pcibr_soft_t pcibr_soft){ uint64_t int_status; uint64_t mult_int; uint64_t bit; int i; int_status = (pcireg_intr_status_get(pcibr_soft) & ~BRIDGE_ISR_INT_MSK); 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, "PIC"); for (i = PCIBR_ISR_ERR_START; i < 64; i++) { bit = 1ull << i; /* A number of int_status bits are only valid for PIC's bus0 */ if ((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", pcireg_parity_err_get(pcibr_soft)); 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%lx\n", pcireg_arbitration_get(pcibr_soft)); 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", pcireg_pcix_req_err_addr_get(pcibr_soft), pcireg_pcix_req_err_attr_get(pcibr_soft)); 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", pcireg_pcix_pio_split_addr_get(pcibr_soft), pcireg_pcix_pio_split_attr_get(pcibr_soft)); /* 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", pcireg_pcix_bus_err_addr_get(pcibr_soft), pcireg_pcix_bus_err_attr_get(pcibr_soft), pcireg_pcix_bus_err_data_get(pcibr_soft)); break; case BRIDGE_ISR_PAGE_FAULT: /* bit30 PMU_PAGE_FAULT */ printk("\t Map Fault Address Reg: 0x%lx\n", pcireg_map_fault_get(pcibr_soft)); break; case BRIDGE_ISR_UNEXP_RESP: /* bit29 UNEXPECTED_RESP */ print_bridge_errcmd(pcibr_soft, pcireg_linkside_err_get(pcibr_soft), "Aux "); /* PIC in PCI-X mode, dump the PCIX DMA Request registers */ if (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", pcireg_pcix_req_err_addr_get(pcibr_soft), pcireg_pcix_req_err_attr_get(pcibr_soft)); } break; case BRIDGE_ISR_BAD_XRESP_PKT: /* bit28 BAD_RESP_PACKET */ case BRIDGE_ISR_RESP_XTLK_ERR: /* bit26 RESP_XTALK_ERROR */ print_bridge_errcmd(pcibr_soft, pcireg_linkside_err_get(pcibr_soft), "Aux "); /* PCI-X mode, DMA Request Error registers are valid. But * 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", pcireg_pcix_req_err_addr_get(pcibr_soft), pcireg_pcix_req_err_attr_get(pcibr_soft)); } else { printk( "\t Bridge Response Buf Error Addr Reg: 0x%lx\n" "\t dev-num %d buff-num %d addr 0x%lx\n", pcireg_resp_err_get(pcibr_soft), (int)pcireg_resp_err_dev_get(pcibr_soft), (int)pcireg_resp_err_buf_get(pcibr_soft), pcireg_resp_err_addr_get(pcibr_soft)); if (bit == BRIDGE_ISR_RESP_XTLK_ERR) { /* display memory directory associated with cacheline */ pcibr_show_dir_state( pcireg_resp_err_get(pcibr_soft), "\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(pcibr_soft, pcireg_cmdword_err_get(pcibr_soft), ""); printk( "\t Bridge Error Address Register: 0x%lx\n" "\t Bridge Error Address: 0x%lx\n", pcireg_bus_err_get(pcibr_soft), pcireg_bus_err_get(pcibr_soft)); break; case BRIDGE_ISR_UNSUPPORTED_XOP: /* bit23 UNSUPPORTED_XOP */ print_bridge_errcmd(pcibr_soft, pcireg_linkside_err_get(pcibr_soft), "Aux "); printk("\t Address Holding Link Side Error Reg: 0x%lx\n", pcireg_linkside_err_addr_get(pcibr_soft)); break; case BRIDGE_ISR_XREQ_FIFO_OFLOW: /* bit22 XREQ_FIFO_OFLOW */ print_bridge_errcmd(pcibr_soft, pcireg_linkside_err_get(pcibr_soft), "Aux "); printk("\t Address Holding Link Side Error Reg: 0x%lx\n", pcireg_linkside_err_addr_get(pcibr_soft)); break; 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 */ printk("\t PCI Error Address Register: 0x%lx\n" "\t PCI Error Address: 0x%lx\n", pcireg_pci_bus_addr_get(pcibr_soft), pcireg_pci_bus_addr_addr_get(pcibr_soft)); break; case BRIDGE_ISR_XREAD_REQ_TIMEOUT: /* bit09 XREAD_REQ_TOUT */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?