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

📄 ipath_iba6120.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		return;	}	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,	 * or it's occurred within the last 5 seconds	 */	if ((hwerrs & ~(dd->ipath_lasthwerror |			((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |			  INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)			 << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT))) ||	    (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) {		/*		 * 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_pe_txe_recover(dd))			hwerrs &= ~TXE_PIO_PARITY;		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_pe_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;			}			/*			 * Mark as having had an error for driver, and also			 * for /sys and status word mapped to user programs.			 * This marks unit as not usable, until reset			 */			*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;			*dd->ipath_statusp |= IPATH_STATUS_HWERROR;			dd->ipath_flags &= ~IPATH_INITTED;		} else {			static u32 freeze_cnt;			freeze_cnt++;			ipath_dbg("Clearing freezemode on ignored or recovered "				  "hardware error (%u)\n", freeze_cnt);			ipath_clear_freeze(dd);		}	}	*msg = '\0';	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_statusp |= IPATH_STATUS_HWERROR;		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,				 dd->ipath_hwerrmask);	}	ipath_format_hwerrors(hwerrs,			      ipath_6120_hwerror_msgs,			      sizeof(ipath_6120_hwerror_msgs)/			      sizeof(ipath_6120_hwerror_msgs[0]),			      msg, msgl);	if (hwerrs & (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK		      << INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT)) {		bits = (u32) ((hwerrs >>			       INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) &			      INFINIPATH_HWE_PCIEMEMPARITYERR_MASK);		snprintf(bitsmsg, sizeof bitsmsg,			 "[PCIe Mem Parity Errs %x] ", bits);		strlcat(msg, bitsmsg, msgl);	}#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP |	\			 INFINIPATH_HWE_COREPLL_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 (*msg)		ipath_dev_err(dd, "%s hardware error\n", msg);	if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) {		/*		 * for /sys status file ; if no trailing } is copied, we'll		 * know it was truncated.		 */		snprintf(dd->ipath_freezemsg, dd->ipath_freezelen,			 "{%s}", msg);	}}/** * ipath_pe_boardname - fill in the board name * @dd: the infinipath device * @name: the output buffer * @namelen: the size of the output buffer * * info is based on the board revision register */static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,			      size_t namelen){	char *n = NULL;	u8 boardrev = dd->ipath_boardrev;	int ret;	switch (boardrev) {	case 0:		n = "InfiniPath_Emulation";		break;	case 1:		n = "InfiniPath_QLE7140-Bringup";		break;	case 2:		n = "InfiniPath_QLE7140";		break;	case 3:		n = "InfiniPath_QMI7140";		break;	case 4:		n = "InfiniPath_QEM7140";		break;	case 5:		n = "InfiniPath_QMH7140";		break;	case 6:		n = "InfiniPath_QLE7142";		break;	default:		ipath_dev_err(dd,			      "Don't yet know about board with ID %u\n",			      boardrev);		snprintf(name, namelen, "Unknown_InfiniPath_PCIe_%u",			 boardrev);		break;	}	if (n)		snprintf(name, namelen, "%s", n);	if (dd->ipath_majrev != 4 || !dd->ipath_minrev || dd->ipath_minrev>2) {		ipath_dev_err(dd, "Unsupported InfiniPath hardware revision %u.%u!\n",			      dd->ipath_majrev, dd->ipath_minrev);		ret = 1;	} else {		ret = 0;		if (dd->ipath_minrev >= 2)			dd->ipath_f_put_tid = ipath_pe_put_tid_2;	}	return ret;}/** * ipath_pe_init_hwerrors - enable hardware errors * @dd: the infinipath device * * now that we have finished initializing everything that might reasonably * cause a hardware error, and cleared those errors bits as they occur, * we can enable hardware errors in the mask (potentially enabling * freeze mode), and enable hardware errors as errors (along with * everything else) in errormask */static void ipath_pe_init_hwerrors(struct ipath_devdata *dd){	ipath_err_t val;	u64 extsval;	extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);	if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST))		ipath_dev_err(dd, "MemBIST did not complete!\n");	if (extsval & INFINIPATH_EXTS_MEMBIST_FOUND)		ipath_dbg("MemBIST corrected\n");	val = ~0ULL;	/* barring bugs, all hwerrors become interrupts, */	if (!dd->ipath_boardrev)	// no PLL for Emulator		val &= ~INFINIPATH_HWE_SERDESPLLFAILED;	if (dd->ipath_minrev < 2) {		/* workaround bug 9460 in internal interface bus parity		 * checking. Fixed (HW bug 9490) in Rev2.		 */		val &= ~INFINIPATH_HWE_PCIEBUSPARITYRADM;	}	dd->ipath_hwerrmask = val;}/** * ipath_pe_bringup_serdes - bring up the serdes * @dd: the infinipath device */static int ipath_pe_bringup_serdes(struct ipath_devdata *dd){	u64 val, config1, prev_val;	int ret = 0;	ipath_dbg("Trying to bringup serdes\n");	if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) &	    INFINIPATH_HWE_SERDESPLLFAILED) {		ipath_dbg("At start, serdes PLL failed bit set "			  "in hwerrstatus, clearing and continuing\n");		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,				 INFINIPATH_HWE_SERDESPLLFAILED);	}	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);	config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1);	ipath_cdbg(VERBOSE, "SerDes status config0=%llx config1=%llx, "		   "xgxsconfig %llx\n", (unsigned long long) val,		   (unsigned long long) config1, (unsigned long long)		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));	/*	 * Force reset on, also set rxdetect enable.  Must do before reading	 * serdesstatus at least for simulation, or some of the bits in	 * serdes status will come back as undefined and cause simulation	 * failures	 */	val |= INFINIPATH_SERDC0_RESET_PLL | INFINIPATH_SERDC0_RXDETECT_EN		| INFINIPATH_SERDC0_L1PWR_DN;	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);	/* be sure chip saw it */	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);	udelay(5);		/* need pll reset set at least for a bit */	/*	 * after PLL is reset, set the per-lane Resets and TxIdle and	 * clear the PLL reset and rxdetect (to get falling edge).	 * Leave L1PWR bits set (permanently)	 */	val &= ~(INFINIPATH_SERDC0_RXDETECT_EN | INFINIPATH_SERDC0_RESET_PLL		 | INFINIPATH_SERDC0_L1PWR_DN);	val |= INFINIPATH_SERDC0_RESET_MASK | INFINIPATH_SERDC0_TXIDLE;	ipath_cdbg(VERBOSE, "Clearing pll reset and setting lane resets "		   "and txidle (%llx)\n", (unsigned long long) val);	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);	/* be sure chip saw it */	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);	/* need PLL reset clear for at least 11 usec before lane	 * resets cleared; give it a few more to be sure */	udelay(15);	val &= ~(INFINIPATH_SERDC0_RESET_MASK | INFINIPATH_SERDC0_TXIDLE);	ipath_cdbg(VERBOSE, "Clearing lane resets and txidle "		   "(writing %llx)\n", (unsigned long long) val);	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);	/* be sure chip saw it */	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);	prev_val = val;	if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &	     INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {		val &=			~(INFINIPATH_XGXS_MDIOADDR_MASK <<			  INFINIPATH_XGXS_MDIOADDR_SHIFT);		/* MDIO address 3 */		val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;	}	if (val & INFINIPATH_XGXS_RESET) {		val &= ~INFINIPATH_XGXS_RESET;	}	if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) &	     INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) {		/* need to compensate for Tx inversion in partner */		val &= ~(INFINIPATH_XGXS_RX_POL_MASK <<		         INFINIPATH_XGXS_RX_POL_SHIFT);		val |= dd->ipath_rx_pol_inv <<			INFINIPATH_XGXS_RX_POL_SHIFT;	}	if (val != prev_val)		ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);	/* clear current and de-emphasis bits */	config1 &= ~0x0ffffffff00ULL;	/* set current to 20ma */	config1 |= 0x00000000000ULL;	/* set de-emphasis to -5.68dB */	config1 |= 0x0cccc000000ULL;	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig1, config1);	ipath_cdbg(VERBOSE, "done: SerDes status config0=%llx "		   "config1=%llx, sstatus=%llx xgxs=%llx\n",		   (unsigned long long) val, (unsigned long long) config1,		   (unsigned long long)		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),		   (unsigned long long)		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));	if (!ipath_waitfor_mdio_cmdready(dd)) {		ipath_write_kreg(			dd, dd->ipath_kregs->kr_mdio,			ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,				       IPATH_MDIO_CTRL_XGXS_REG_8, 0));		if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,					   IPATH_MDIO_DATAVALID, &val))

⌨️ 快捷键说明

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