📄 pci_schizo.c
字号:
* the hardware and we must re-read to get a clean value. */ limit = 1000; do { afsr = schizo_read(afsr_reg); } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); /* Clear primary/secondary error status bits. */ error_bits = afsr & (SCHIZO_CEAFSR_PPIO | SCHIZO_CEAFSR_PDRD | SCHIZO_CEAFSR_PDWR | SCHIZO_CEAFSR_SPIO | SCHIZO_CEAFSR_SDMA); if (!error_bits) return; schizo_write(afsr_reg, error_bits); /* Log the error. */ printk("PCI%d: Correctable Error, primary error type[%s]\n", p->index, (((error_bits & SCHIZO_CEAFSR_PPIO) ? "PIO" : ((error_bits & SCHIZO_CEAFSR_PDRD) ? "DMA Read" : ((error_bits & SCHIZO_CEAFSR_PDWR) ? "DMA Write" : "???"))))); /* XXX Use syndrome and afar to print out module string just like * XXX UDB CE trap handler does... -DaveM */ printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", p->index, (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL, (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL, (afsr & SCHIZO_UEAFSR_AID) >> 24UL); printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", p->index, (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0, (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0, (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL, (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL, (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL); printk("PCI%d: CE AFAR [%016lx]\n", p->index, afar); printk("PCI%d: CE Secondary errors [", p->index); reported = 0; if (afsr & SCHIZO_CEAFSR_SPIO) { reported++; printk("(PIO)"); } if (afsr & SCHIZO_CEAFSR_SDMA) { reported++; printk("(DMA)"); } if (!reported) printk("(none)"); printk("]\n"); schizo_clear_other_err_intr(irq);}#define SCHIZO_PCI_AFSR 0x2010UL#define SCHIZO_PCI_AFAR 0x2018UL#define SCHIZO_PCIAFSR_PMA 0x8000000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_PTA 0x4000000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_PRTRY 0x2000000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_PPERR 0x1000000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_PTTO 0x0800000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_PUNUS 0x0400000000000000UL /* Schizo */#define SCHIZO_PCIAFSR_SMA 0x0200000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_STA 0x0100000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_SRTRY 0x0080000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_SPERR 0x0040000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_STTO 0x0020000000000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_SUNUS 0x0010000000000000UL /* Schizo */#define SCHIZO_PCIAFSR_BMSK 0x000003ff00000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_BLK 0x0000000080000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_CFG 0x0000000040000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_MEM 0x0000000020000000UL /* Schizo/Tomatillo */#define SCHIZO_PCIAFSR_IO 0x0000000010000000UL /* Schizo/Tomatillo */#define SCHIZO_PCI_CTRL (0x2000UL)#define SCHIZO_PCICTRL_BUS_UNUS (1UL << 63UL) /* Safari */#define SCHIZO_PCICTRL_ARB_PRIO (0x1ff << 52UL) /* Tomatillo */#define SCHIZO_PCICTRL_ESLCK (1UL << 51UL) /* Safari */#define SCHIZO_PCICTRL_ERRSLOT (7UL << 48UL) /* Safari */#define SCHIZO_PCICTRL_TTO_ERR (1UL << 38UL) /* Safari/Tomatillo */#define SCHIZO_PCICTRL_RTRY_ERR (1UL << 37UL) /* Safari/Tomatillo */#define SCHIZO_PCICTRL_DTO_ERR (1UL << 36UL) /* Safari/Tomatillo */#define SCHIZO_PCICTRL_SBH_ERR (1UL << 35UL) /* Safari */#define SCHIZO_PCICTRL_SERR (1UL << 34UL) /* Safari/Tomatillo */#define SCHIZO_PCICTRL_PCISPD (1UL << 33UL) /* Safari */#define SCHIZO_PCICTRL_MRM_PREF (1UL << 28UL) /* Tomatillo */#define SCHIZO_PCICTRL_RDO_PREF (1UL << 27UL) /* Tomatillo */#define SCHIZO_PCICTRL_RDL_PREF (1UL << 26UL) /* Tomatillo */#define SCHIZO_PCICTRL_PTO (3UL << 24UL) /* Safari/Tomatillo */#define SCHIZO_PCICTRL_PTO_SHIFT 24UL#define SCHIZO_PCICTRL_TRWSW (7UL << 21UL) /* Tomatillo */#define SCHIZO_PCICTRL_F_TGT_A (1UL << 20UL) /* Tomatillo */#define SCHIZO_PCICTRL_S_DTO_INT (1UL << 19UL) /* Safari */#define SCHIZO_PCICTRL_F_TGT_RT (1UL << 19UL) /* Tomatillo */#define SCHIZO_PCICTRL_SBH_INT (1UL << 18UL) /* Safari */#define SCHIZO_PCICTRL_T_DTO_INT (1UL << 18UL) /* Tomatillo */#define SCHIZO_PCICTRL_EEN (1UL << 17UL) /* Safari/Tomatillo */#define SCHIZO_PCICTRL_PARK (1UL << 16UL) /* Safari/Tomatillo */#define SCHIZO_PCICTRL_PCIRST (1UL << 8UL) /* Safari */#define SCHIZO_PCICTRL_ARB_S (0x3fUL << 0UL) /* Safari */#define SCHIZO_PCICTRL_ARB_T (0xffUL << 0UL) /* Tomatillo */static void schizo_pcierr_intr_other(struct pci_pbm_info *pbm){ unsigned long csr_reg, csr, csr_error_bits; u16 stat; csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; csr = schizo_read(csr_reg); csr_error_bits = csr & (SCHIZO_PCICTRL_BUS_UNUS | SCHIZO_PCICTRL_TTO_ERR | SCHIZO_PCICTRL_RTRY_ERR | SCHIZO_PCICTRL_DTO_ERR | SCHIZO_PCICTRL_SBH_ERR | SCHIZO_PCICTRL_SERR); if (csr_error_bits) { /* Clear the errors. */ schizo_write(csr_reg, csr); /* Log 'em. */ if (csr_error_bits & SCHIZO_PCICTRL_BUS_UNUS) printk("%s: Bus unusable error asserted.\n", pbm->name); if (csr_error_bits & SCHIZO_PCICTRL_TTO_ERR) printk("%s: PCI TRDY# timeout error asserted.\n", pbm->name); if (csr_error_bits & SCHIZO_PCICTRL_RTRY_ERR) printk("%s: PCI excessive retry error asserted.\n", pbm->name); if (csr_error_bits & SCHIZO_PCICTRL_DTO_ERR) printk("%s: PCI discard timeout error asserted.\n", pbm->name); if (csr_error_bits & SCHIZO_PCICTRL_SBH_ERR) printk("%s: PCI streaming byte hole error asserted.\n", pbm->name); if (csr_error_bits & SCHIZO_PCICTRL_SERR) printk("%s: PCI SERR signal asserted.\n", pbm->name); } pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); if (stat & (PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_SIG_SYSTEM_ERROR)) { printk("%s: PCI bus error, PCI_STATUS[%04x]\n", pbm->name, stat); pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); }}static void schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs){ struct pci_pbm_info *pbm = dev_id; struct pci_controller_info *p = pbm->parent; unsigned long afsr_reg, afar_reg, base; unsigned long afsr, afar, error_bits; int reported; base = pbm->pbm_regs; afsr_reg = base + SCHIZO_PCI_AFSR; afar_reg = base + SCHIZO_PCI_AFAR; /* Latch error status. */ afar = schizo_read(afar_reg); afsr = schizo_read(afsr_reg); /* Clear primary/secondary error status bits. */ error_bits = afsr & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS); if (!error_bits) return schizo_pcierr_intr_other(pbm); schizo_write(afsr_reg, error_bits); /* Log the error. */ printk("%s: PCI Error, primary error type[%s]\n", pbm->name, (((error_bits & SCHIZO_PCIAFSR_PMA) ? "Master Abort" : ((error_bits & SCHIZO_PCIAFSR_PTA) ? "Target Abort" : ((error_bits & SCHIZO_PCIAFSR_PRTRY) ? "Excessive Retries" : ((error_bits & SCHIZO_PCIAFSR_PPERR) ? "Parity Error" : ((error_bits & SCHIZO_PCIAFSR_PTTO) ? "Timeout" : ((error_bits & SCHIZO_PCIAFSR_PUNUS) ? "Bus Unusable" : "???")))))))); printk("%s: bytemask[%04lx] was_block(%d) space(%s)\n", pbm->name, (afsr & SCHIZO_PCIAFSR_BMSK) >> 32UL, (afsr & SCHIZO_PCIAFSR_BLK) ? 1 : 0, ((afsr & SCHIZO_PCIAFSR_CFG) ? "Config" : ((afsr & SCHIZO_PCIAFSR_MEM) ? "Memory" : ((afsr & SCHIZO_PCIAFSR_IO) ? "I/O" : "???")))); printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); printk("%s: PCI Secondary errors [", pbm->name); reported = 0; if (afsr & SCHIZO_PCIAFSR_SMA) { reported++; printk("(Master Abort)"); } if (afsr & SCHIZO_PCIAFSR_STA) { reported++; printk("(Target Abort)"); } if (afsr & SCHIZO_PCIAFSR_SRTRY) { reported++; printk("(Excessive Retries)"); } if (afsr & SCHIZO_PCIAFSR_SPERR) { reported++; printk("(Parity Error)"); } if (afsr & SCHIZO_PCIAFSR_STTO) { reported++; printk("(Timeout)"); } if (afsr & SCHIZO_PCIAFSR_SUNUS) { reported++; printk("(Bus Unusable)"); } if (!reported) printk("(none)"); printk("]\n"); /* For the error types shown, scan PBM's PCI bus for devices * which have logged that error type. */ /* If we see a Target Abort, this could be the result of an * IOMMU translation error of some sort. It is extremely * useful to log this information as usually it indicates * a bug in the IOMMU support code or a PCI device driver. */ if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { schizo_check_iommu_error(p, PCI_ERR); pci_scan_for_target_abort(p, pbm, pbm->pci_bus); } if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) pci_scan_for_master_abort(p, pbm, pbm->pci_bus); /* For excessive retries, PSYCHO/PBM will abort the device * and there is no way to specifically check for excessive * retries in the config space status registers. So what * we hope is that we'll catch it via the master/target * abort events. */ if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR)) pci_scan_for_parity_error(p, pbm, pbm->pci_bus); schizo_clear_other_err_intr(irq);}#define SCHIZO_SAFARI_ERRLOG 0x10018UL#define SAFARI_ERRLOG_ERROUT 0x8000000000000000UL#define BUS_ERROR_BADCMD 0x4000000000000000UL /* Schizo/Tomatillo */#define BUS_ERROR_SSMDIS 0x2000000000000000UL /* Safari */#define BUS_ERROR_BADMA 0x1000000000000000UL /* Safari */#define BUS_ERROR_BADMB 0x0800000000000000UL /* Safari */#define BUS_ERROR_BADMC 0x0400000000000000UL /* Safari */#define BUS_ERROR_SNOOP_GR 0x0000000000200000UL /* Tomatillo */#define BUS_ERROR_SNOOP_PCI 0x0000000000100000UL /* Tomatillo */#define BUS_ERROR_SNOOP_RD 0x0000000000080000UL /* Tomatillo */#define BUS_ERROR_SNOOP_RDS 0x0000000000020000UL /* Tomatillo */#define BUS_ERROR_SNOOP_RDSA 0x0000000000010000UL /* Tomatillo */#define BUS_ERROR_SNOOP_OWN 0x0000000000008000UL /* Tomatillo */#define BUS_ERROR_SNOOP_RDO 0x0000000000004000UL /* Tomatillo */#define BUS_ERROR_CPU1PS 0x0000000000002000UL /* Safari */#define BUS_ERROR_WDATA_PERR 0x0000000000002000UL /* Tomatillo */#define BUS_ERROR_CPU1PB 0x0000000000001000UL /* Safari */#define BUS_ERROR_CTRL_PERR 0x0000000000001000UL /* Tomatillo */#define BUS_ERROR_CPU0PS 0x0000000000000800UL /* Safari */#define BUS_ERROR_SNOOP_ERR 0x0000000000000800UL /* Tomatillo */#define BUS_ERROR_CPU0PB 0x0000000000000400UL /* Safari */#define BUS_ERROR_JBUS_ILL_B 0x0000000000000400UL /* Tomatillo */#define BUS_ERROR_CIQTO 0x0000000000000200UL /* Safari */#define BUS_ERROR_LPQTO 0x0000000000000100UL /* Safari */#define BUS_ERROR_JBUS_ILL_C 0x0000000000000100UL /* Tomatillo */#define BUS_ERROR_SFPQTO 0x0000000000000080UL /* Safari */#define BUS_ERROR_UFPQTO 0x0000000000000040UL /* Safari */#define BUS_ERROR_RD_PERR 0x0000000000000040UL /* Tomatillo */#define BUS_ERROR_APERR 0x0000000000000020UL /* Safari/Tomatillo */#define BUS_ERROR_UNMAP 0x0000000000000010UL /* Safari/Tomatillo */#define BUS_ERROR_BUSERR 0x0000000000000004UL /* Safari/Tomatillo */#define BUS_ERROR_TIMEOUT 0x0000000000000002UL /* Safari/Tomatillo */#define BUS_ERROR_ILL 0x0000000000000001UL /* Safari *//* We only expect UNMAP errors here. The rest of the Safari errors * are marked fatal and thus cause a system reset. */static void schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *regs){ struct pci_controller_info *p = dev_id; u64 errlog; errlog = schizo_read(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG); schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG, errlog & ~(SAFARI_ERRLOG_ERROUT)); if (!(errlog & BUS_ERROR_UNMAP)) { printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", p->index, errlog); schizo_clear_other_err_intr(irq); return; } printk("PCI%d: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", p->index); schizo_check_iommu_error(p, SAFARI_ERR); schizo_clear_other_err_intr(irq);}/* Nearly identical to PSYCHO equivalents... */#define SCHIZO_ECC_CTRL 0x10020UL#define SCHIZO_ECCCTRL_EE 0x8000000000000000 /* Enable ECC Checking */#define SCHIZO_ECCCTRL_UE 0x4000000000000000 /* Enable UE Interrupts */#define SCHIZO_ECCCTRL_CE 0x2000000000000000 /* Enable CE INterrupts */#define SCHIZO_SAFARI_ERRCTRL 0x10008UL#define SCHIZO_SAFERRCTRL_EN 0x8000000000000000UL#define SCHIZO_SAFARI_IRQCTRL 0x10010UL#define SCHIZO_SAFIRQCTRL_EN 0x8000000000000000UL#define SCHIZO_UE_INO 0x30 /* Uncorrectable ECC error */#define SCHIZO_CE_INO 0x31 /* Correctable ECC error */#define SCHIZO_PCIERR_A_INO 0x32 /* PBM A PCI bus error */#define SCHIZO_PCIERR_B_INO 0x33 /* PBM B PCI bus error */#define SCHIZO_SERR_INO 0x34 /* Safari interface error */struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino){ ino &= IMAP_INO; if (p->pbm_A.ino_bitmap & (1UL << ino)) return &p->pbm_A; if (p->pbm_B.ino_bitmap & (1UL << ino)) return &p->pbm_B; prom_printf("TOMATILLO%d: No entry in ino bitmap for %d\n", p->index, ino); prom_halt(); /* NOTREACHED */ return NULL;}/* How the Tomatillo IRQs are routed around is pure guesswork here. * * All the Tomatillo devices I see in prtconf dumps seem to have only * a single PCI bus unit attached to it. It would seem they are seperate * devices because their PortID (ie. JBUS ID) values are all different * and thus the registers are mapped to totally different locations. * * However, two Tomatillo's look "similar" in that the only difference * in their PortID is the lowest bit. * * So if we were to ignore this lower bit, it certainly looks like two * PCI bus units of the same Tomatillo. I still have not really * figured this out... */static void __init tomatillo_register_error_handlers(struct pci_controller_info *p){ struct pci_pbm_info *pbm; unsigned int irq; struct ino_bucket *bucket; u64 tmp, err_mask, err_no_mask; /* Build IRQs and register handlers. */ pbm = pbm_for_ino(p, SCHIZO_UE_INO); irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO); if (request_irq(irq, schizo_ue_intr, SA_SHIRQ, "TOMATILLO UE", p) < 0) { prom_printf("%s: Cannot register UE interrupt.\n", pbm->name); prom_halt(); } bucket = __bucket(irq); tmp = readl(bucket->imap); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_CE_INO); irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO); if (request_irq(irq, schizo_ce_intr, SA_SHIRQ, "TOMATILLO CE", p) < 0) { prom_printf("%s: Cannot register CE interrupt.\n", pbm->name); prom_halt(); } bucket = __bucket(irq); tmp = upa_readl(bucket->imap); upa_writel(tmp, (pbm->pbm_regs +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -