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

📄 ipath_iba6110.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	INFINIPATH_HWE_MSG(RXDSYNCMEMPARITYERR, "Rx Dsync"),	INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"),};#define TXE_PIO_PARITY ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF | \		        INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) \		        << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)#define RXE_EAGER_PARITY (INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID \			  << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)static int ipath_ht_txe_recover(struct ipath_devdata *);/** * ipath_ht_handle_hwerrors - display hardware errors. * @dd: the infinipath device * @msg: the output buffer * @msgl: the size of the output buffer * * Use same msg buffer as regular errors to avoid excessive stack * use.  Most hardware errors are catastrophic, but for right now, * we'll print them and continue.  We reuse the same message buffer as * ipath_handle_errors() to avoid excessive stack usage. */static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,				     size_t msgl){	ipath_err_t hwerrs;	u32 bits, ctrl;	int isfatal = 0;	char bitsmsg[64];	int log_idx;	hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);	if (!hwerrs) {		ipath_cdbg(VERBOSE, "Called but no hardware errors set\n");		/*		 * better than printing cofusing messages		 * This seems to be related to clearing the crc error, or		 * the pll error during init.		 */		goto bail;	} else if (hwerrs == -1LL) {		ipath_dev_err(dd, "Read of hardware error status failed "			      "(all bits set); ignoring\n");		goto bail;	}	ipath_stats.sps_hwerrs++;	/* Always clear the error status register, except MEMBISTFAIL,	 * regardless of whether we continue or stop using the chip.	 * We want that set so we know it failed, even across driver reload.	 * We'll still ignore it in the hwerrmask.  We do this partly for	 * diagnostics, but also for support */	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,			 hwerrs&~INFINIPATH_HWE_MEMBISTFAILED);	hwerrs &= dd->ipath_hwerrmask;	/* We log some errors to EEPROM, check if we have any of those. */	for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx)		if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log)			ipath_inc_eeprom_err(dd, log_idx, 1);	/*	 * make sure we get this much out, unless told to be quiet,	 * it's a parity error we may recover from,	 * or it's occurred within the last 5 seconds	 */	if ((hwerrs & ~(dd->ipath_lasthwerror | TXE_PIO_PARITY |		RXE_EAGER_PARITY)) ||		(ipath_debug & __IPATH_VERBDBG))		dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "			 "(cleared)\n", (unsigned long long) hwerrs);	dd->ipath_lasthwerror |= hwerrs;	if (hwerrs & ~dd->ipath_hwe_bitsextant)		ipath_dev_err(dd, "hwerror interrupt with unknown errors "			      "%llx set\n", (unsigned long long)			      (hwerrs & ~dd->ipath_hwe_bitsextant));	ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);	if ((ctrl & INFINIPATH_C_FREEZEMODE) && !ipath_diag_inuse) {		/*		 * parity errors in send memory are recoverable,		 * just cancel the send (if indicated in * sendbuffererror),		 * count the occurrence, unfreeze (if no other handled		 * hardware error bits are set), and continue. They can		 * occur if a processor speculative read is done to the PIO		 * buffer while we are sending a packet, for example.		 */		if ((hwerrs & TXE_PIO_PARITY) && ipath_ht_txe_recover(dd))			hwerrs &= ~TXE_PIO_PARITY;		if (hwerrs & RXE_EAGER_PARITY)			ipath_dev_err(dd, "RXE parity, Eager TID error is not "				"recoverable\n");		if (!hwerrs) {			ipath_dbg("Clearing freezemode on ignored or "				  "recovered hardware error\n");			ipath_clear_freeze(dd);		}	}	*msg = '\0';	/*	 * may someday want to decode into which bits are which	 * functional area for parity errors, etc.	 */	if (hwerrs & (infinipath_hwe_htcmemparityerr_mask		      << INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT)) {		bits = (u32) ((hwerrs >>			       INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) &			      INFINIPATH_HWE_HTCMEMPARITYERR_MASK);		snprintf(bitsmsg, sizeof bitsmsg, "[HTC Parity Errs %x] ",			 bits);		strlcat(msg, bitsmsg, msgl);	}	ipath_format_hwerrors(hwerrs,			      ipath_6110_hwerror_msgs,			      sizeof(ipath_6110_hwerror_msgs) /			      sizeof(ipath_6110_hwerror_msgs[0]),			      msg, msgl);	if (hwerrs & (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS))		hwerr_crcbits(dd, hwerrs, msg, msgl);	if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {		strlcat(msg, "[Memory BIST test failed, InfiniPath hardware unusable]",			msgl);		/* ignore from now on, so disable until driver reloaded */		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,				 dd->ipath_hwerrmask);	}#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP |	\			 INFINIPATH_HWE_COREPLL_RFSLIP |	\			 INFINIPATH_HWE_HTBPLL_FBSLIP |		\			 INFINIPATH_HWE_HTBPLL_RFSLIP |		\			 INFINIPATH_HWE_HTAPLL_FBSLIP |		\			 INFINIPATH_HWE_HTAPLL_RFSLIP)	if (hwerrs & _IPATH_PLL_FAIL) {		snprintf(bitsmsg, sizeof bitsmsg,			 "[PLL failed (%llx), InfiniPath hardware unusable]",			 (unsigned long long) (hwerrs & _IPATH_PLL_FAIL));		strlcat(msg, bitsmsg, msgl);		/* ignore from now on, so disable until driver reloaded */		dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,				 dd->ipath_hwerrmask);	}	if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {		/*		 * If it occurs, it is left masked since the eternal		 * interface is unused		 */		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,				 dd->ipath_hwerrmask);	}	if (hwerrs) {		/*		 * if any set that we aren't ignoring; only		 * make the complaint once, in case it's stuck		 * or recurring, and we get here multiple		 * times.		 * force link down, so switch knows, and		 * LEDs are turned off		 */		if (dd->ipath_flags & IPATH_INITTED) {			ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);			ipath_setup_ht_setextled(dd,				INFINIPATH_IBCS_L_STATE_DOWN,				INFINIPATH_IBCS_LT_STATE_DISABLED);			ipath_dev_err(dd, "Fatal Hardware Error (freeze "					  "mode), no longer usable, SN %.16s\n",					  dd->ipath_serial);			isfatal = 1;		}		*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;		/* mark as having had error */		*dd->ipath_statusp |= IPATH_STATUS_HWERROR;		/*		 * mark as not usable, at a minimum until driver		 * is reloaded, probably until reboot, since no		 * other reset is possible.		 */		dd->ipath_flags &= ~IPATH_INITTED;	}	else		*msg = 0; /* recovered from all of them */	if (*msg)		ipath_dev_err(dd, "%s hardware error\n", msg);	if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg)		/*		 * for status file; if no trailing brace is copied,		 * we'll know it was truncated.		 */		snprintf(dd->ipath_freezemsg,			 dd->ipath_freezelen, "{%s}", msg);bail:;}/** * ipath_ht_boardname - fill in the board name * @dd: the infinipath device * @name: the output buffer * @namelen: the size of the output buffer * * fill in the board name, based on the board revision register */static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,			      size_t namelen){	char *n = NULL;	u8 boardrev = dd->ipath_boardrev;	int ret = 0;	switch (boardrev) {	case 5:		/*		 * original production board; two production levels, with		 * different serial number ranges.   See ipath_ht_early_init() for		 * case where we enable IPATH_GPIO_INTR for later serial # range.		 * Original 112* serial number is no longer supported.		 */		n = "InfiniPath_QHT7040";		break;	case 7:		/* small form factor production board */		n = "InfiniPath_QHT7140";		break;	default:		/* don't know, just print the number */		ipath_dev_err(dd, "Don't yet know about board "			      "with ID %u\n", boardrev);		snprintf(name, namelen, "Unknown_InfiniPath_QHT7xxx_%u",			 boardrev);		ret = 1;		break;	}	if (n)		snprintf(name, namelen, "%s", n);	if (ret) {		ipath_dev_err(dd, "Unsupported InfiniPath board %s!\n", name);		goto bail;	}	if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 ||		dd->ipath_minrev > 4)) {		/*		 * This version of the driver only supports Rev 3.2 - 3.4		 */		ipath_dev_err(dd,			      "Unsupported InfiniPath hardware revision %u.%u!\n",			      dd->ipath_majrev, dd->ipath_minrev);		ret = 1;		goto bail;	}	/*	 * pkt/word counters are 32 bit, and therefore wrap fast enough	 * that we snapshot them from a timer, and maintain 64 bit shadow	 * copies	 */	dd->ipath_flags |= IPATH_32BITCOUNTERS;	dd->ipath_flags |= IPATH_GPIO_INTR;	if (dd->ipath_htspeed != 800)		ipath_dev_err(dd,			      "Incorrectly configured for HT @ %uMHz\n",			      dd->ipath_htspeed);	ret = 0;bail:	return ret;}static void ipath_check_htlink(struct ipath_devdata *dd){	u8 linkerr, link_off, i;	for (i = 0; i < 2; i++) {		link_off = dd->ipath_ht_slave_off + i * 4 + 0xd;		if (pci_read_config_byte(dd->pcidev, link_off, &linkerr))			dev_info(&dd->pcidev->dev, "Couldn't read "				 "linkerror%d of HT slave/primary block\n",				 i);		else if (linkerr & 0xf0) {			ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, "				   "clearing\n", linkerr >> 4, i);			/*			 * writing the linkerr bits that are set should			 * clear them			 */			if (pci_write_config_byte(dd->pcidev, link_off,						  linkerr))				ipath_dbg("Failed write to clear HT "					  "linkerror%d\n", i);			if (pci_read_config_byte(dd->pcidev, link_off,						 &linkerr))				dev_info(&dd->pcidev->dev,					 "Couldn't reread linkerror%d of "					 "HT slave/primary block\n", i);			else if (linkerr & 0xf0)				dev_info(&dd->pcidev->dev,					 "HT linkerror%d bits 0x%x "					 "couldn't be cleared\n",					 i, linkerr >> 4);		}	}}static int ipath_setup_ht_reset(struct ipath_devdata *dd){	ipath_dbg("No reset possible for this InfiniPath hardware\n");	return 0;}#define HT_INTR_DISC_CONFIG  0x80	/* HT interrupt and discovery cap */#define HT_INTR_REG_INDEX    2	/* intconfig requires indirect accesses *//* * Bits 13-15 of command==0 is slave/primary block.  Clear any HT CRC * errors.  We only bother to do this at load time, because it's OK if * it happened before we were loaded (first time after boot/reset), * but any time after that, it's fatal anyway.  Also need to not check * for for upper byte errors if we are in 8 bit mode, so figure out * our width.  For now, at least, also complain if it's 8 bit. */static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,			     int pos, u8 cap_type){	u8 linkwidth = 0, linkerr, link_a_b_off, link_off;	u16 linkctrl = 0;	int i;	dd->ipath_ht_slave_off = pos;	/* command word, master_host bit */	/* master host || slave */	if ((cap_type >> 2) & 1)		link_a_b_off = 4;	else		link_a_b_off = 0;	ipath_cdbg(VERBOSE, "HT%u (Link %c) connected to processor\n",		   link_a_b_off ? 1 : 0,		   link_a_b_off ? 'B' : 'A');	link_a_b_off += pos;	/*	 * check both link control registers; clear both HT CRC sets if	 * necessary.	 */	for (i = 0; i < 2; i++) {		link_off = pos + i * 4 + 0x4;		if (pci_read_config_word(pdev, link_off, &linkctrl))			ipath_dev_err(dd, "Couldn't read HT link control%d "				      "register\n", i);		else if (linkctrl & (0xf << 8)) {			ipath_cdbg(VERBOSE, "Clear linkctrl%d CRC Error "				   "bits %x\n", i, linkctrl & (0xf << 8));			/*			 * now write them back to clear the error.			 */			pci_write_config_byte(pdev, link_off,					      linkctrl & (0xf << 8));		}	}	/*	 * As with HT CRC bits, same for protocol errors that might occur	 * during boot.	 */	for (i = 0; i < 2; i++) {		link_off = pos + i * 4 + 0xd;		if (pci_read_config_byte(pdev, link_off, &linkerr))			dev_info(&pdev->dev, "Couldn't read linkerror%d "				 "of HT slave/primary block\n", i);		else if (linkerr & 0xf0) {			ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, "				   "clearing\n", linkerr >> 4, i);			/*			 * writing the linkerr bits that are set will clear			 * them			 */			if (pci_write_config_byte			    (pdev, link_off, linkerr))				ipath_dbg("Failed write to clear HT "					  "linkerror%d\n", i);			if (pci_read_config_byte(pdev, link_off, &linkerr))				dev_info(&pdev->dev, "Couldn't reread "					 "linkerror%d of HT slave/primary "					 "block\n", i);			else if (linkerr & 0xf0)				dev_info(&pdev->dev, "HT linkerror%d bits "					 "0x%x couldn't be cleared\n",					 i, linkerr >> 4);		}	}	/*	 * this is just for our link to the host, not devices connected	 * through tunnel.	 */	if (pci_read_config_byte(pdev, link_a_b_off + 7, &linkwidth))		ipath_dev_err(dd, "Couldn't read HT link width "			      "config register\n");	else {

⌨️ 快捷键说明

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