⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcibr_error.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		    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,		    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(			"\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:	    /* 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;	    }	}    }    /* 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)	\		(( 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;    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;    iopaddr_t		    base;    size_t		    size;    unsigned		    win;    int			    func;    bridge = soft->bs_base;    /* 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]);		}	    }	}    }}/* * PCI Bridge Error interrupt handler. *      This gets invoked, whenever a PCI bridge sends an error interrupt. *      Primarily this servers two purposes. *              - If an error can be handled (typically a PIO read/write *                error, we try to do it silently. *              - If an error cannot be handled, we die violently. *      Interrupt due to PIO errors: *              - Bridge sends an interrupt, whenever a PCI operation *                done by the bridge as the master fails. Operations could *                be either a PIO read or a PIO write. *                PIO Read operation also triggers a bus error, and it's *                We primarily ignore this interrupt in that context.. *                For PIO write errors, this is the only indication. *                and we have to handle with the info from here. * *                So, there is no way to distinguish if an interrupt is *                due to read or write error!. */voidpcibr_error_intr_handler(int irq, void *arg, struct pt_regs *ep){    pcibr_soft_t            pcibr_soft;    bridge_t               *bridge;    uint64_t              int_status;    uint64_t              err_status;    bridgereg_t             int_status_32;    picreg_t                int_status_64;    int			    number_bits;    int                     i;    /* REFERENCED */    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;	entry = pcibr_list;	while (1) {	    if (entry == NULL) {		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 /* PCIBR_SOFT_LIST */    pcibr_soft = (pcibr_soft_t) arg;    bridge = pcibr_soft->bs_base;    /*     * pcibr_error_intr_handler gets invoked whenever bridge encounters     * an error situation, and the interrupt for that error is enabled.     * This routine decides if the error is fatal or not, and takes     * action accordingly.     *     * In the case of PIO read/write timeouts, there is no way     * to know if it was a read or write request that timed out.     * If the error was due to a "read", a bus error will also occur     * and the bus error handling code takes care of it.      * If the error is due to a "write", the error is currently logged      * by this routine. For SN1 and SN0, if fire-and-forget mode is      * disabled, a write error response xtalk packet will be sent to      * the II, which will cause an II error interrupt. No write error      * recovery actions of any kind currently take place at the pcibr      * layer! (e.g., no panic on unrecovered write error)     *     * Prior to reading the Bridge int_status register we need to ensure     * that there are no error bits set in the lower layers (hubii)     * that have disabled PIO access to the widget. If so, there is nothing     * we can do until the bits clear, so we setup a timeout and try again     * later.     */    nasid = NASID_GET(bridge);    if (hubii_check_widget_disabled(nasid, pcibr_soft->bs_xid)) {	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;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -