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

📄 pcibr_error.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
     */    if ((err_status & BRIDGE_ISR_INVLD_ADDR) &&	((((uint64_t) bridge->b_wid_err_upper << 32) | (bridge->b_wid_err_lower))	 == (BRIDGE_INT_RST_STAT & 0xff0))) {	pcibr_llp_control_war_cnt++;	err_status &= ~BRIDGE_ISR_INVLD_ADDR;    }    bridge_errors_to_dump |= BRIDGE_ISR_PCIBUS_PIOERR;    /* Dump/Log Bridge error interrupt info */    if (err_status & bridge_errors_to_dump) {	printk("BRIDGE ERR_STATUS 0x%lx\n", err_status);	pcibr_error_dump(pcibr_soft);    }    /* PIC BRINGUP WAR (PV# 867308):     * Make BRIDGE_ISR_LLP_REC_SNERR & BRIDGE_ISR_LLP_REC_CBERR fatal errors     * so we know we've hit the problem defined in PV 867308 that we believe     * has only been seen in simulation     */    if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV867308, pcibr_soft) &&        (err_status & (BRIDGE_ISR_LLP_REC_SNERR | BRIDGE_ISR_LLP_REC_CBERR))) {        printk("BRIDGE ERR_STATUS 0x%lx\n", err_status);        pcibr_error_dump(pcibr_soft);        panic("PCI Bridge Error interrupt killed the system");    }    if (err_status & BRIDGE_ISR_ERROR_FATAL) {	panic("PCI Bridge Error interrupt killed the system");	    /*NOTREACHED */    }    /*     * We can't return without re-enabling the interrupt, since     * it would cause problems for devices like IOC3 (Lost     * interrupts ?.). So, just cleanup the interrupt, and     * use saved values later..     *      * PIC doesn't require groups of interrupts to be cleared...     */    if (IS_PIC_SOFT(pcibr_soft)) {	bridge->p_int_rst_stat_64 = (picreg_t)(int_status | BRIDGE_IRR_MULTI_CLR);    } else {	bridge->b_int_rst_stat = (bridgereg_t)pcibr_errintr_group(int_status);    }    /* PIC BRINGUP WAR (PV# 856155):     * On a PCI_X_ARB_ERR error interrupt clear the DEV_BROKE bits from     * the b_arb register to re-enable the device.     */    if (IS_PIC_SOFT(pcibr_soft) &&		(err_status & PIC_ISR_PCIX_ARB_ERR) &&		PCIBR_WAR_ENABLED(PV856155, pcibr_soft)) {	bridge->b_arb |= (0xf << 20);    }    /* Zero out bserr_intstat field */    pcibr_soft->bs_errinfo.bserr_intstat = 0;}voidpcibr_error_cleanup(pcibr_soft_t pcibr_soft, int error_code){    bridge_t               *bridge = pcibr_soft->bs_base;    ASSERT(error_code & IOECODE_PIO);    error_code = error_code;    if (IS_PIC_SOFT(pcibr_soft)) {        bridge->p_int_rst_stat_64 = BRIDGE_IRR_PCI_GRP_CLR |				    PIC_PCIX_GRP_CLR |				    BRIDGE_IRR_MULTI_CLR;    } else {        bridge->b_int_rst_stat = BRIDGE_IRR_PCI_GRP_CLR | BRIDGE_IRR_MULTI_CLR;    }    (void) bridge->b_wid_tflush;	/* flushbus */}/*ARGSUSED */voidpcibr_device_disable(pcibr_soft_t pcibr_soft, int devnum){    /*     * XXX     * Device failed to handle error. Take steps to     * disable this device ? HOW TO DO IT ?     *     * If there are any Read response buffers associated     * with this device, it's time to get them back!!     *     * We can disassociate any interrupt level associated     * with this device, and disable that interrupt level     *     * For now it's just a place holder     */}/* * pcibr_pioerror *      Handle PIO error that happened at the bridge pointed by pcibr_soft. * *      Queries the Bus interface attached to see if the device driver *      mapping the device-number that caused error can handle the *      situation. If so, it will clean up any error, and return *      indicating the error was handled. If the device driver is unable *      to handle the error, it expects the bus-interface to disable that *      device, and takes any steps needed here to take away any resources *      associated with this device. *//* BEM_ADD_IOE doesn't dump the whole ioerror, it just * decodes the PCI specific portions -- we count on our * callers to dump the raw IOE data. */#define BEM_ADD_IOE(ioe)						\	do {								\	    if (IOERROR_FIELDVALID(ioe, busspace)) {			\		iopaddr_t		spc;				\		iopaddr_t		win;				\		short			widdev;				\		iopaddr_t		busaddr;			\									\		IOERROR_GETVALUE(spc, ioe, busspace);			\		win = spc - PCIIO_SPACE_WIN(0);				\		IOERROR_GETVALUE(busaddr, ioe, busaddr);		\		IOERROR_GETVALUE(widdev, ioe, widgetdev);		\									\		switch (spc) {						\		case PCIIO_SPACE_CFG:					\		    printk("\tPCI Slot %d Func %d CFG space Offset 0x%lx\n",\			    	pciio_widgetdev_slot_get(widdev),	\	    			pciio_widgetdev_func_get(widdev),	\				busaddr);				\		    break;						\		case PCIIO_SPACE_IO:					\		    printk("\tPCI I/O space  Offset 0x%lx\n", busaddr);	\		    break;						\		case PCIIO_SPACE_MEM:					\		case PCIIO_SPACE_MEM32:					\		case PCIIO_SPACE_MEM64:					\		    printk("\tPCI MEM space Offset 0x%lx\n", busaddr);	\		    break;						\		default:						\		    if (win < 6) {					\		    printk("\tPCI Slot %d Func %d Window %ld Offset 0x%lx\n",\	    			pciio_widgetdev_slot_get(widdev),	\	    			pciio_widgetdev_func_get(widdev),	\			    	win,					\			    	busaddr);				\		    }							\		    break;						\		}							\	    }								\	} while (0)/*ARGSUSED */intpcibr_pioerror(		  pcibr_soft_t pcibr_soft,		  int error_code,		  ioerror_mode_t mode,		  ioerror_t *ioe){    int                     retval = IOERROR_HANDLED;    vertex_hdl_t            pcibr_vhdl = pcibr_soft->bs_vhdl;#if defined(FORCE_ERRORS)    bridge_t               *bridge = pcibr_soft->bs_base;#endif    iopaddr_t               bad_xaddr;    pciio_space_t           raw_space;	/* raw PCI space */    iopaddr_t               raw_paddr;	/* raw PCI address */    pciio_space_t           space;	/* final PCI space */    pciio_slot_t            slot;	/* final PCI slot, if appropriate */    pciio_function_t        func;	/* final PCI func, if appropriate */    iopaddr_t               offset;	/* final PCI offset */        int                     cs, cw, cf;    pciio_space_t           wx;    iopaddr_t               wb;    size_t                  ws;    iopaddr_t               wl;    /*     * We expect to have an "xtalkaddr" coming in,     * and need to construct the slot/space/offset.     */    IOERROR_GETVALUE(bad_xaddr, ioe, xtalkaddr);    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn,                "pcibr_pioerror: pcibr_soft=0x%x, bad_xaddr=0x%x\n",		pcibr_soft, bad_xaddr));    slot = PCIIO_SLOT_NONE;    func = PCIIO_FUNC_NONE;    raw_space = PCIIO_SPACE_NONE;    raw_paddr = 0;    if ((bad_xaddr >= PCIBR_BUS_TYPE0_CFG_DEV0(pcibr_soft)) &&	(bad_xaddr < PCIBR_TYPE1_CFG(pcibr_soft))) {	raw_paddr = bad_xaddr - PCIBR_BUS_TYPE0_CFG_DEV0(pcibr_soft);	slot = raw_paddr / BRIDGE_TYPE0_CFG_SLOT_OFF;	raw_paddr = raw_paddr % BRIDGE_TYPE0_CFG_SLOT_OFF;	raw_space = PCIIO_SPACE_CFG;    }    if ((bad_xaddr >= PCIBR_TYPE1_CFG(pcibr_soft)) &&	(bad_xaddr < (PCIBR_TYPE1_CFG(pcibr_soft) + 0x1000))) {	/* Type 1 config space:	 * slot and function numbers not known.	 * Perhaps we can read them back?	 */	raw_paddr = bad_xaddr - PCIBR_TYPE1_CFG(pcibr_soft);	raw_space = PCIIO_SPACE_CFG;    }    if ((bad_xaddr >= PCIBR_BRIDGE_DEVIO0(pcibr_soft)) &&	(bad_xaddr < PCIBR_BRIDGE_DEVIO(pcibr_soft, BRIDGE_DEV_CNT))) {	int                     x;	raw_paddr = bad_xaddr - PCIBR_BRIDGE_DEVIO0(pcibr_soft);	x = raw_paddr / BRIDGE_DEVIO_OFF;	raw_paddr %= BRIDGE_DEVIO_OFF;	/* first two devio windows are double-sized */	if ((x == 1) || (x == 3))	    raw_paddr += BRIDGE_DEVIO_OFF;	if (x > 0)	    x--;	if (x > 1)	    x--;	/* x is which devio reg; no guarantee	 * PCI slot x will be responding.	 * still need to figure out who decodes	 * space/offset on the bus.	 */	raw_space = pcibr_soft->bs_slot[x].bss_devio.bssd_space;	if (raw_space == PCIIO_SPACE_NONE) {	    /* Someone got an error because they	     * accessed the PCI bus via a DevIO(x)	     * window that pcibr has not yet assigned	     * to any specific PCI address. It is	     * quite possible that the Device(x)	     * register has been changed since they	     * made their access, but we will give it	     * our best decode shot.	     */	    raw_space = pcibr_soft->bs_slot[x].bss_device		& BRIDGE_DEV_DEV_IO_MEM		? PCIIO_SPACE_MEM		: PCIIO_SPACE_IO;	    raw_paddr +=		(pcibr_soft->bs_slot[x].bss_device &		 BRIDGE_DEV_OFF_MASK) <<		BRIDGE_DEV_OFF_ADDR_SHFT;	} else	    raw_paddr += pcibr_soft->bs_slot[x].bss_devio.bssd_base;    }    if ((bad_xaddr >= BRIDGE_PCI_MEM32_BASE) &&	(bad_xaddr <= BRIDGE_PCI_MEM32_LIMIT)) {	raw_space = PCIIO_SPACE_MEM32;	raw_paddr = bad_xaddr - BRIDGE_PCI_MEM32_BASE;    }    if ((bad_xaddr >= BRIDGE_PCI_MEM64_BASE) &&	(bad_xaddr <= BRIDGE_PCI_MEM64_LIMIT)) {	raw_space = PCIIO_SPACE_MEM64;	raw_paddr = bad_xaddr - BRIDGE_PCI_MEM64_BASE;    }    if ((bad_xaddr >= BRIDGE_PCI_IO_BASE) &&	(bad_xaddr <= BRIDGE_PCI_IO_LIMIT)) {	raw_space = PCIIO_SPACE_IO;	raw_paddr = bad_xaddr - BRIDGE_PCI_IO_BASE;    }    space = raw_space;    offset = raw_paddr;    if ((slot == PCIIO_SLOT_NONE) && (space != PCIIO_SPACE_NONE)) {	/* we've got a space/offset but not which	 * PCI slot decodes it. Check through our	 * notions of which devices decode where.	 *	 * Yes, this "duplicates" some logic in	 * pcibr_addr_toslot; the difference is,	 * this code knows which space we are in,	 * and can really really tell what is	 * going on (no guessing).	 */	for (cs = pcibr_soft->bs_min_slot; 		(cs < PCIBR_NUM_SLOTS(pcibr_soft)) && 					(slot == PCIIO_SLOT_NONE); cs++) {	    int                     nf = pcibr_soft->bs_slot[cs].bss_ninfo;	    pcibr_info_h            pcibr_infoh = pcibr_soft->bs_slot[cs].bss_infos;	    for (cf = 0; (cf < nf) && (slot == PCIIO_SLOT_NONE); cf++) {		pcibr_info_t            pcibr_info = pcibr_infoh[cf];		if (!pcibr_info)		    continue;		for (cw = 0; (cw < 6) && (slot == PCIIO_SLOT_NONE); ++cw) {		    if (((wx = pcibr_info->f_window[cw].w_space) != PCIIO_SPACE_NONE) &&			((wb = pcibr_info->f_window[cw].w_base) != 0) &&			((ws = pcibr_info->f_window[cw].w_size) != 0) &&			((wl = wb + ws) > wb) &&			((wb <= offset) && (wl > offset))) {			/* MEM, MEM32 and MEM64 need to			 * compare as equal ...			 */			if ((wx == space) ||			    (((wx == PCIIO_SPACE_MEM) ||			      (wx == PCIIO_SPACE_MEM32) ||			      (wx == PCIIO_SPACE_MEM64)) &&			     ((space == PCIIO_SPACE_MEM) ||			      (space == PCIIO_SPACE_MEM32) ||			      (space == PCIIO_SPACE_MEM64)))) {			    slot = cs;			    func = cf;			    space = PCIIO_SPACE_WIN(cw);			    offset -= wb;			}		/* endif window space match */		    }			/* endif window valid and addr match */		}			/* next window unless slot set */	    }				/* next func unless slot set */	}				/* next slot unless slot set */	/* XXX- if slot is still -1, no PCI devices are	 * decoding here using their standard PCI BASE	 * registers. This would be a really good place	 * to cross-coordinate with the pciio PCI	 * address space allocation routines, to find	 * out if this address is "allocated" by any of	 * our subsidiary devices.	 */    }    /* Scan all piomap records on this PCI bus to update     * the TimeOut Counters on all matching maps. If we     * don't already know the slot number, take it from     * the first matching piomap. Note that we have to     * compare maps against raw_space and raw_paddr     * since space and offset could already be     * window-relative.     *     * There is a chance that one CPU could update     * through this path, and another CPU could also     * update due to an interrupt. Closing this hole     * would only result in the possibility of some     * errors never getting logged at all, and since the     * use for bp_toc is as a logical test rather than a     * strict count, the excess counts are not a     * problem.     */    for (cs = pcibr_soft->bs_min_slot; 				cs < PCIBR_NUM_SLOTS(pcibr_soft); ++cs) {	int 		nf = pcibr_soft->bs_slot[cs].bss_ninfo;	pcibr_info_h	pcibr_infoh = pcibr_soft->bs_slot[cs].bss_infos;	for (cf = 0; cf < nf; cf++) {	    pcibr_info_t 	pcibr_info = pcibr_infoh[cf];	    pcibr_piomap_t	map;    	    if (!pcibr_info)		continue;	    for (map = pcibr_info->f_piomap;	     map != NULL; map = map->bp_next) {	    wx = map->bp_space;	    wb = map->bp_pciaddr;	    ws = map->bp_mapsz;	    cw = wx - PCIIO_SPACE_WIN(0);	    if (cw < 6) {		wb += pcibr_soft->bs_slot[cs].bss_window[cw].bssw_base;		wx = pcibr_soft->bs_slot[cs].bss_window[cw].bssw_space;	    }	    if (wx == PCIIO_SPACE_ROM) {		wb += pcibr_info->f_rbase;		wx = PCIIO_SPACE_MEM;	    }	    if ((wx == PCIIO_SPACE_MEM32) ||		(wx == PCIIO_SPACE_MEM64))		wx = PCIIO_SPACE_MEM;	    wl = wb + ws;	    if ((wx == raw_space) && (raw_paddr >= wb) && (raw_paddr < wl)) {		atomic_inc(&map->bp_toc[0]);		if (slot == PCIIO_SLOT_NONE) {		    slot = cs;		    space = map->bp_space;		    if (cw < 6)			offset -= pcibr_soft->bs_slot[cs].bss_window[cw].bssw_base;		}	    }	    }	}    }    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn,                "pcibr_pioerror: offset=0x%x, slot=0x%x, func=0x%x\n",		offset, slot, func));    if (space != PCIIO_SPACE_NONE) {	if (slot != PCIIO_SLOT_NONE) {	    if (func != PCIIO_FUNC_NONE) {		IOERROR_SETVALUE(ioe, widgetdev, 				 pciio_widgetdev_create(slot,func));	    }	    else {    		IOERROR_SETVALUE(ioe, widgetdev, 				 pciio_widgetdev_create(slot,0));	    }	}	IOERROR_SETVALUE(ioe, busspace, space);	IOERROR_SETVALUE(ioe, busaddr, offset);    }    if (mode == MODE_DEVPROBE) {	/*	 * During probing, we don't really care what the	 * error is. Clean up the error in Bridge, notify	 * subsidiary devices, and return success.	 */	pcibr_error_cleanup(pcibr_soft, error_code);	/* if appropriate, give the error handler for this slot	 * a shot at this probe access as well.	 */	return (slot == PCIIO_SLOT_NONE) ? IOERROR_HANDLED :	    pciio_error_handler(pcibr_vhdl, error_code, mode, ioe);    }    /*     * If we don't know what "PCI SPACE" the access     * was targeting, we may have problems at the     * Bridge itself. Don't touch any bridge registers,     * and do complain loudly.     */    if (space == PCIIO_SPACE_NONE) {	printk("XIO Bus Error at %s\n"		"\taccess to XIO bus offset 0x%lx\n"		"\tdoes not correspond to any PCI address\n",		pcibr_soft->bs_name, bad_xaddr);	/* caller will dump contents of ioe struct */	return IOERROR_XTALKLEVEL;    }    /*     * Actual PCI Error handling situation.     * Typically happens when a user level process accesses     * PCI space, and it causes some error.     *     * Due to PCI Bridge implementation, we get two indication     * for a read error: an interrupt and a Bus error.     * We like to handle read error in the bus error context.     * But the interrupt comes and goes before bus error

⌨️ 快捷键说明

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