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

📄 pci_schizo.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	iclr += 4;	/* On Schizo, no inofixup occurs.  This is because each	 * INO has it's own IMAP register.  On Psycho and Sabre	 * there is only one IMAP register for each PCI slot even	 * though four different INOs can be generated by each	 * PCI slot.	 *	 * But, for JBUS variants (essentially, Tomatillo), we have	 * to fixup the lowest bit of the interrupt group number.	 */	ign_fixup = 0;	if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {		if (pbm->portid & 1)			ign_fixup = (1 << 6);	}	bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap));	bucket->flags |= IBF_PCI;	return __irq(bucket);}/* SCHIZO error handling support. */enum schizo_error_type {	UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR};static spinlock_t stc_buf_lock = SPIN_LOCK_UNLOCKED;static unsigned long stc_error_buf[128];static unsigned long stc_tag_buf[16];static unsigned long stc_line_buf[16];/* These offsets look weird because I keep in pbm->controller_regs * the second PROM register property minus 0x10000 which is the * base of the Safari and UPA64S registers of SCHIZO. */#define SCHIZO_PBM_A_REGS_OFF	(0x600000UL - 0x400000UL)#define SCHIZO_PBM_B_REGS_OFF	(0x700000UL - 0x400000UL)static void schizo_clear_other_err_intr(int irq){	struct ino_bucket *bucket = __bucket(irq);	unsigned long iclr = bucket->iclr;	iclr += (SCHIZO_PBM_B_REGS_OFF - SCHIZO_PBM_A_REGS_OFF);	upa_writel(ICLR_IDLE, iclr);}#define SCHIZO_STC_ERR	0xb800UL /* --> 0xba00 */#define SCHIZO_STC_TAG	0xba00UL /* --> 0xba80 */#define SCHIZO_STC_LINE	0xbb00UL /* --> 0xbb80 */#define SCHIZO_STCERR_WRITE	0x2UL#define SCHIZO_STCERR_READ	0x1UL#define SCHIZO_STCTAG_PPN	0x3fffffff00000000UL#define SCHIZO_STCTAG_VPN	0x00000000ffffe000UL#define SCHIZO_STCTAG_VALID	0x8000000000000000UL#define SCHIZO_STCTAG_READ	0x4000000000000000UL#define SCHIZO_STCLINE_LINDX	0x0000000007800000UL#define SCHIZO_STCLINE_SPTR	0x000000000007e000UL#define SCHIZO_STCLINE_LADDR	0x0000000000001fc0UL#define SCHIZO_STCLINE_EPTR	0x000000000000003fUL#define SCHIZO_STCLINE_VALID	0x0000000000600000UL#define SCHIZO_STCLINE_FOFN	0x0000000000180000ULstatic void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm,					 enum schizo_error_type type){	struct pci_strbuf *strbuf = &pbm->stc;	unsigned long regbase = pbm->pbm_regs;	unsigned long err_base, tag_base, line_base;	u64 control;	int i;	err_base = regbase + SCHIZO_STC_ERR;	tag_base = regbase + SCHIZO_STC_TAG;	line_base = regbase + SCHIZO_STC_LINE;	spin_lock(&stc_buf_lock);	/* This is __REALLY__ dangerous.  When we put the	 * streaming buffer into diagnostic mode to probe	 * it's tags and error status, we _must_ clear all	 * of the line tag valid bits before re-enabling	 * the streaming buffer.  If any dirty data lives	 * in the STC when we do this, we will end up	 * invalidating it before it has a chance to reach	 * main memory.	 */	control = schizo_read(strbuf->strbuf_control);	schizo_write(strbuf->strbuf_control,		     (control | SCHIZO_STRBUF_CTRL_DENAB));	for (i = 0; i < 128; i++) {		unsigned long val;		val = schizo_read(err_base + (i * 8UL));		schizo_write(err_base + (i * 8UL), 0UL);		stc_error_buf[i] = val;	}	for (i = 0; i < 16; i++) {		stc_tag_buf[i] = schizo_read(tag_base + (i * 8UL));		stc_line_buf[i] = schizo_read(line_base + (i * 8UL));		schizo_write(tag_base + (i * 8UL), 0UL);		schizo_write(line_base + (i * 8UL), 0UL);	}	/* OK, state is logged, exit diagnostic mode. */	schizo_write(strbuf->strbuf_control, control);	for (i = 0; i < 16; i++) {		int j, saw_error, first, last;		saw_error = 0;		first = i * 8;		last = first + 8;		for (j = first; j < last; j++) {			unsigned long errval = stc_error_buf[j];			if (errval != 0) {				saw_error++;				printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n",				       pbm->name,				       j,				       (errval & SCHIZO_STCERR_WRITE) ? 1 : 0,				       (errval & SCHIZO_STCERR_READ) ? 1 : 0);			}		}		if (saw_error != 0) {			unsigned long tagval = stc_tag_buf[i];			unsigned long lineval = stc_line_buf[i];			printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)R(%d)]\n",			       pbm->name,			       i,			       ((tagval & SCHIZO_STCTAG_PPN) >> 19UL),			       (tagval & SCHIZO_STCTAG_VPN),			       ((tagval & SCHIZO_STCTAG_VALID) ? 1 : 0),			       ((tagval & SCHIZO_STCTAG_READ) ? 1 : 0));			/* XXX Should spit out per-bank error information... -DaveM */			printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)"			       "V(%d)FOFN(%d)]\n",			       pbm->name,			       i,			       ((lineval & SCHIZO_STCLINE_LINDX) >> 23UL),			       ((lineval & SCHIZO_STCLINE_SPTR) >> 13UL),			       ((lineval & SCHIZO_STCLINE_LADDR) >> 6UL),			       ((lineval & SCHIZO_STCLINE_EPTR) >> 0UL),			       ((lineval & SCHIZO_STCLINE_VALID) ? 1 : 0),			       ((lineval & SCHIZO_STCLINE_FOFN) ? 1 : 0));		}	}	spin_unlock(&stc_buf_lock);}/* IOMMU is per-PBM in Schizo, so interrogate both for anonymous * controller level errors. */#define SCHIZO_IOMMU_TAG	0xa580UL#define SCHIZO_IOMMU_DATA	0xa600UL#define SCHIZO_IOMMU_TAG_CTXT	0x0000001ffe000000UL#define SCHIZO_IOMMU_TAG_ERRSTS	0x0000000001800000UL#define SCHIZO_IOMMU_TAG_ERR	0x0000000000400000UL#define SCHIZO_IOMMU_TAG_WRITE	0x0000000000200000UL#define SCHIZO_IOMMU_TAG_STREAM	0x0000000000100000UL#define SCHIZO_IOMMU_TAG_SIZE	0x0000000000080000UL#define SCHIZO_IOMMU_TAG_VPAGE	0x000000000007ffffUL#define SCHIZO_IOMMU_DATA_VALID	0x0000000100000000UL#define SCHIZO_IOMMU_DATA_CACHE	0x0000000040000000UL#define SCHIZO_IOMMU_DATA_PPAGE	0x000000003fffffffULstatic void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,					 enum schizo_error_type type){	struct pci_iommu *iommu = pbm->iommu;	unsigned long iommu_tag[16];	unsigned long iommu_data[16];	unsigned long flags;	u64 control;	int i;	spin_lock_irqsave(&iommu->lock, flags);	control = schizo_read(iommu->iommu_control);	if (control & SCHIZO_IOMMU_CTRL_XLTEERR) {		unsigned long base;		char *type_string;		/* Clear the error encountered bit. */		control &= ~SCHIZO_IOMMU_CTRL_XLTEERR;		schizo_write(iommu->iommu_control, control);		switch((control & SCHIZO_IOMMU_CTRL_XLTESTAT) >> 25UL) {		case 0:			type_string = "Protection Error";			break;		case 1:			type_string = "Invalid Error";			break;		case 2:			type_string = "TimeOut Error";			break;		case 3:		default:			type_string = "ECC Error";			break;		};		printk("%s: IOMMU Error, type[%s]\n",		       pbm->name, type_string);		/* Put the IOMMU into diagnostic mode and probe		 * it's TLB for entries with error status.		 *		 * It is very possible for another DVMA to occur		 * while we do this probe, and corrupt the system		 * further.  But we are so screwed at this point		 * that we are likely to crash hard anyways, so		 * get as much diagnostic information to the		 * console as we can.		 */		schizo_write(iommu->iommu_control,			     control | SCHIZO_IOMMU_CTRL_DENAB);		base = pbm->pbm_regs;		for (i = 0; i < 16; i++) {			iommu_tag[i] =				schizo_read(base + SCHIZO_IOMMU_TAG + (i * 8UL));			iommu_data[i] =				schizo_read(base + SCHIZO_IOMMU_DATA + (i * 8UL));			/* Now clear out the entry. */			schizo_write(base + SCHIZO_IOMMU_TAG + (i * 8UL), 0);			schizo_write(base + SCHIZO_IOMMU_DATA + (i * 8UL), 0);		}		/* Leave diagnostic mode. */		schizo_write(iommu->iommu_control, control);		for (i = 0; i < 16; i++) {			unsigned long tag, data;			tag = iommu_tag[i];			if (!(tag & SCHIZO_IOMMU_TAG_ERR))				continue;			data = iommu_data[i];			switch((tag & SCHIZO_IOMMU_TAG_ERRSTS) >> 23UL) {			case 0:				type_string = "Protection Error";				break;			case 1:				type_string = "Invalid Error";				break;			case 2:				type_string = "TimeOut Error";				break;			case 3:			default:				type_string = "ECC Error";				break;			};			printk("%s: IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) "			       "sz(%dK) vpg(%08lx)]\n",			       pbm->name, i, type_string,			       (int)((tag & SCHIZO_IOMMU_TAG_CTXT) >> 25UL),			       ((tag & SCHIZO_IOMMU_TAG_WRITE) ? 1 : 0),			       ((tag & SCHIZO_IOMMU_TAG_STREAM) ? 1 : 0),			       ((tag & SCHIZO_IOMMU_TAG_SIZE) ? 64 : 8),			       (tag & SCHIZO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT);			printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n",			       pbm->name, i,			       ((data & SCHIZO_IOMMU_DATA_VALID) ? 1 : 0),			       ((data & SCHIZO_IOMMU_DATA_CACHE) ? 1 : 0),			       (data & SCHIZO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT);		}	}	if (pbm->stc.strbuf_enabled)		__schizo_check_stc_error_pbm(pbm, type);	spin_unlock_irqrestore(&iommu->lock, flags);}static void schizo_check_iommu_error(struct pci_controller_info *p,				     enum schizo_error_type type){	schizo_check_iommu_error_pbm(&p->pbm_A, type);	schizo_check_iommu_error_pbm(&p->pbm_B, type);}/* Uncorrectable ECC error status gathering. */#define SCHIZO_UE_AFSR	0x10030UL#define SCHIZO_UE_AFAR	0x10038UL#define SCHIZO_UEAFSR_PPIO	0x8000000000000000UL /* Safari */#define SCHIZO_UEAFSR_PDRD	0x4000000000000000UL /* Safari/Tomatillo */#define SCHIZO_UEAFSR_PDWR	0x2000000000000000UL /* Safari */#define SCHIZO_UEAFSR_SPIO	0x1000000000000000UL /* Safari */#define SCHIZO_UEAFSR_SDMA	0x0800000000000000UL /* Safari/Tomatillo */#define SCHIZO_UEAFSR_ERRPNDG	0x0300000000000000UL /* Safari */#define SCHIZO_UEAFSR_BMSK	0x000003ff00000000UL /* Safari */#define SCHIZO_UEAFSR_QOFF	0x00000000c0000000UL /* Safari/Tomatillo */#define SCHIZO_UEAFSR_AID	0x000000001f000000UL /* Safari/Tomatillo */#define SCHIZO_UEAFSR_PARTIAL	0x0000000000800000UL /* Safari */#define SCHIZO_UEAFSR_OWNEDIN	0x0000000000400000UL /* Safari */#define SCHIZO_UEAFSR_MTAGSYND	0x00000000000f0000UL /* Safari */#define SCHIZO_UEAFSR_MTAG	0x000000000000e000UL /* Safari */#define SCHIZO_UEAFSR_ECCSYND	0x00000000000001ffUL /* Safari */static void schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs){	struct pci_controller_info *p = dev_id;	unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR;	unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFAR;	unsigned long afsr, afar, error_bits;	int reported, limit;	/* Latch uncorrectable error status. */	afar = schizo_read(afar_reg);	/* If either of the error pending bits are set in the	 * AFSR, the error status is being actively updated by	 * 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 the primary/secondary error status bits. */	error_bits = afsr &		(SCHIZO_UEAFSR_PPIO | SCHIZO_UEAFSR_PDRD | SCHIZO_UEAFSR_PDWR |		 SCHIZO_UEAFSR_SPIO | SCHIZO_UEAFSR_SDMA);	if (!error_bits)		return;	schizo_write(afsr_reg, error_bits);	/* Log the error. */	printk("PCI%d: Uncorrectable Error, primary error type[%s]\n",	       p->index,	       (((error_bits & SCHIZO_UEAFSR_PPIO) ?		 "PIO" :		 ((error_bits & SCHIZO_UEAFSR_PDRD) ?		  "DMA Read" :		  ((error_bits & SCHIZO_UEAFSR_PDWR) ?		   "DMA Write" : "???")))));	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: UE AFAR [%016lx]\n", p->index, afar);	printk("PCI%d: UE Secondary errors [", p->index);	reported = 0;	if (afsr & SCHIZO_UEAFSR_SPIO) {		reported++;		printk("(PIO)");	}	if (afsr & SCHIZO_UEAFSR_SDMA) {		reported++;		printk("(DMA)");	}	if (!reported)		printk("(none)");	printk("]\n");	/* Interrogate IOMMU for error status. */	schizo_check_iommu_error(p, UE_ERR);	schizo_clear_other_err_intr(irq);}#define SCHIZO_CE_AFSR	0x10040UL#define SCHIZO_CE_AFAR	0x10048UL#define SCHIZO_CEAFSR_PPIO	0x8000000000000000UL#define SCHIZO_CEAFSR_PDRD	0x4000000000000000UL#define SCHIZO_CEAFSR_PDWR	0x2000000000000000UL#define SCHIZO_CEAFSR_SPIO	0x1000000000000000UL#define SCHIZO_CEAFSR_SDMA	0x0800000000000000UL#define SCHIZO_CEAFSR_ERRPNDG	0x0300000000000000UL#define SCHIZO_CEAFSR_BMSK	0x000003ff00000000UL#define SCHIZO_CEAFSR_QOFF	0x00000000c0000000UL#define SCHIZO_CEAFSR_AID	0x000000001f000000UL#define SCHIZO_CEAFSR_PARTIAL	0x0000000000800000UL#define SCHIZO_CEAFSR_OWNEDIN	0x0000000000400000UL#define SCHIZO_CEAFSR_MTAGSYND	0x00000000000f0000UL#define SCHIZO_CEAFSR_MTAG	0x000000000000e000UL#define SCHIZO_CEAFSR_ECCSYND	0x00000000000001ffULstatic void schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs){	struct pci_controller_info *p = dev_id;	unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR;	unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFAR;	unsigned long afsr, afar, error_bits;	int reported, limit;	/* Latch error status. */	afar = schizo_read(afar_reg);	/* If either of the error pending bits are set in the	 * AFSR, the error status is being actively updated by

⌨️ 快捷键说明

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