📄 pcibr_error.c
字号:
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 + -