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 + -
显示快捷键?