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

📄 ipath_iba6110.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		u32 width;		switch (linkwidth & 7) {		case 5:			width = 4;			break;		case 4:			width = 2;			break;		case 3:			width = 32;			break;		case 1:			width = 16;			break;		case 0:		default:	/* if wrong, assume 8 bit */			width = 8;			break;		}		dd->ipath_htwidth = width;		if (linkwidth != 0x11) {			ipath_dev_err(dd, "Not configured for 16 bit HT "				      "(%x)\n", linkwidth);			if (!(linkwidth & 0xf)) {				ipath_dbg("Will ignore HT lane1 errors\n");				dd->ipath_flags |= IPATH_8BIT_IN_HT0;			}		}	}	/*	 * this is just for our link to the host, not devices connected	 * through tunnel.	 */	if (pci_read_config_byte(pdev, link_a_b_off + 0xd, &linkwidth))		ipath_dev_err(dd, "Couldn't read HT link frequency "			      "config register\n");	else {		u32 speed;		switch (linkwidth & 0xf) {		case 6:			speed = 1000;			break;		case 5:			speed = 800;			break;		case 4:			speed = 600;			break;		case 3:			speed = 500;			break;		case 2:			speed = 400;			break;		case 1:			speed = 300;			break;		default:			/*			 * assume reserved and vendor-specific are 200...			 */		case 0:			speed = 200;			break;		}		dd->ipath_htspeed = speed;	}}static int ipath_ht_intconfig(struct ipath_devdata *dd){	int ret;	if (dd->ipath_intconfig) {		ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig,				 dd->ipath_intconfig);	/* interrupt address */		ret = 0;	} else {		ipath_dev_err(dd, "No interrupts enabled, couldn't setup "			      "interrupt address\n");		ret = -EINVAL;	}	return ret;}static void ipath_ht_irq_update(struct pci_dev *dev, int irq,				struct ht_irq_msg *msg){	struct ipath_devdata *dd = pci_get_drvdata(dev);	u64 prev_intconfig = dd->ipath_intconfig;	dd->ipath_intconfig = msg->address_lo;	dd->ipath_intconfig |= ((u64) msg->address_hi) << 32;	/*	 * If the previous value of dd->ipath_intconfig is zero, we're	 * getting configured for the first time, and must not program the	 * intconfig register here (it will be programmed later, when the	 * hardware is ready).  Otherwise, we should.	 */	if (prev_intconfig)		ipath_ht_intconfig(dd);}/** * ipath_setup_ht_config - setup the interruptconfig register * @dd: the infinipath device * @pdev: the PCI device * * setup the interruptconfig register from the HT config info. * Also clear CRC errors in HT linkcontrol, if necessary. * This is done only for the real hardware.  It is done before * chip address space is initted, so can't touch infinipath registers */static int ipath_setup_ht_config(struct ipath_devdata *dd,				 struct pci_dev *pdev){	int pos, ret;	ret = __ht_create_irq(pdev, 0, ipath_ht_irq_update);	if (ret < 0) {		ipath_dev_err(dd, "Couldn't create interrupt handler: "			      "err %d\n", ret);		goto bail;	}	dd->ipath_irq = ret;	ret = 0;	/*	 * Handle clearing CRC errors in linkctrl register if necessary.  We	 * do this early, before we ever enable errors or hardware errors,	 * mostly to avoid causing the chip to enter freeze mode.	 */	pos = pci_find_capability(pdev, PCI_CAP_ID_HT);	if (!pos) {		ipath_dev_err(dd, "Couldn't find HyperTransport "			      "capability; no interrupts\n");		ret = -ENODEV;		goto bail;	}	do {		u8 cap_type;		/* the HT capability type byte is 3 bytes after the		 * capability byte.		 */		if (pci_read_config_byte(pdev, pos + 3, &cap_type)) {			dev_info(&pdev->dev, "Couldn't read config "				 "command @ %d\n", pos);			continue;		}		if (!(cap_type & 0xE0))			slave_or_pri_blk(dd, pdev, pos, cap_type);	} while ((pos = pci_find_next_capability(pdev, pos,						 PCI_CAP_ID_HT)));bail:	return ret;}/** * ipath_setup_ht_cleanup - clean up any per-chip chip-specific stuff * @dd: the infinipath device * * Called during driver unload. * This is currently a nop for the HT chip, not for all chips */static void ipath_setup_ht_cleanup(struct ipath_devdata *dd){}/** * ipath_setup_ht_setextled - set the state of the two external LEDs * @dd: the infinipath device * @lst: the L state * @ltst: the LT state * * Set the state of the two external LEDs, to indicate physical and * logical state of IB link.   For this chip (at least with recommended * board pinouts), LED1 is Green (physical state), and LED2 is Yellow * (logical state) * * Note:  We try to match the Mellanox HCA LED behavior as best * we can.  Green indicates physical link state is OK (something is * plugged in, and we can train). * Amber indicates the link is logically up (ACTIVE). * Mellanox further blinks the amber LED to indicate data packet * activity, but we have no hardware support for that, so it would * require waking up every 10-20 msecs and checking the counters * on the chip, and then turning the LED off if appropriate.  That's * visible overhead, so not something we will do. * */static void ipath_setup_ht_setextled(struct ipath_devdata *dd,				     u64 lst, u64 ltst){	u64 extctl;	unsigned long flags = 0;	/* the diags use the LED to indicate diag info, so we leave	 * the external LED alone when the diags are running */	if (ipath_diag_inuse)		return;	/* Allow override of LED display for, e.g. Locating system in rack */	if (dd->ipath_led_override) {		ltst = (dd->ipath_led_override & IPATH_LED_PHYS)			? INFINIPATH_IBCS_LT_STATE_LINKUP			: INFINIPATH_IBCS_LT_STATE_DISABLED;		lst = (dd->ipath_led_override & IPATH_LED_LOG)			? INFINIPATH_IBCS_L_STATE_ACTIVE			: INFINIPATH_IBCS_L_STATE_DOWN;	}	spin_lock_irqsave(&dd->ipath_gpio_lock, flags);	/*	 * start by setting both LED control bits to off, then turn	 * on the appropriate bit(s).	 */	if (dd->ipath_boardrev == 8) { /* LS/X-1 uses different pins */		/*		 * major difference is that INFINIPATH_EXTC_LEDGBLERR_OFF		 * is inverted,  because it is normally used to indicate		 * a hardware fault at reset, if there were errors		 */		extctl = (dd->ipath_extctrl & ~INFINIPATH_EXTC_LEDGBLOK_ON)			| INFINIPATH_EXTC_LEDGBLERR_OFF;		if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)			extctl &= ~INFINIPATH_EXTC_LEDGBLERR_OFF;		if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)			extctl |= INFINIPATH_EXTC_LEDGBLOK_ON;	}	else {		extctl = dd->ipath_extctrl &			~(INFINIPATH_EXTC_LED1PRIPORT_ON |			  INFINIPATH_EXTC_LED2PRIPORT_ON);		if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)			extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;		if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)			extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;	}	dd->ipath_extctrl = extctl;	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);	spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);}static void ipath_init_ht_variables(struct ipath_devdata *dd){	dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;	dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;	dd->ipath_gpio_sda = IPATH_GPIO_SDA;	dd->ipath_gpio_scl = IPATH_GPIO_SCL;	dd->ipath_i_bitsextant =		(INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |		(INFINIPATH_I_RCVAVAIL_MASK <<		 INFINIPATH_I_RCVAVAIL_SHIFT) |		INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |		INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO;	dd->ipath_e_bitsextant =		INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |		INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |		INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |		INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR |		INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |		INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |		INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |		INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |		INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |		INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN |		INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN |		INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT |		INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |		INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED |		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET |		INFINIPATH_E_HARDWARE;	dd->ipath_hwe_bitsextant =		(INFINIPATH_HWE_HTCMEMPARITYERR_MASK <<		 INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) |		(INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<		 INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) |		(INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<		 INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |		INFINIPATH_HWE_HTCLNKABYTE0CRCERR |		INFINIPATH_HWE_HTCLNKABYTE1CRCERR |		INFINIPATH_HWE_HTCLNKBBYTE0CRCERR |		INFINIPATH_HWE_HTCLNKBBYTE1CRCERR |		INFINIPATH_HWE_HTCMISCERR4 |		INFINIPATH_HWE_HTCMISCERR5 | INFINIPATH_HWE_HTCMISCERR6 |		INFINIPATH_HWE_HTCMISCERR7 |		INFINIPATH_HWE_HTCBUSTREQPARITYERR |		INFINIPATH_HWE_HTCBUSTRESPPARITYERR |		INFINIPATH_HWE_HTCBUSIREQPARITYERR |		INFINIPATH_HWE_RXDSYNCMEMPARITYERR |		INFINIPATH_HWE_MEMBISTFAILED |		INFINIPATH_HWE_COREPLL_FBSLIP |		INFINIPATH_HWE_COREPLL_RFSLIP |		INFINIPATH_HWE_HTBPLL_FBSLIP |		INFINIPATH_HWE_HTBPLL_RFSLIP |		INFINIPATH_HWE_HTAPLL_FBSLIP |		INFINIPATH_HWE_HTAPLL_RFSLIP |		INFINIPATH_HWE_SERDESPLLFAILED |		INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |		INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;	dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;	dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;	/*	 * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.	 * 2 is Some Misc, 3 is reserved for future.	 */	dd->ipath_eep_st_masks[0].hwerrs_to_log =		INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<		INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT;	dd->ipath_eep_st_masks[1].hwerrs_to_log =		INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<		INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;	dd->ipath_eep_st_masks[2].errs_to_log =		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;}/** * ipath_ht_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_ht_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_CORRECT)		ipath_dbg("MemBIST corrected\n");	ipath_check_htlink(dd);	/* barring bugs, all hwerrors become interrupts, which can */	val = -1LL;	/* don't look at crc lane1 if 8 bit */	if (dd->ipath_flags & IPATH_8BIT_IN_HT0)		val &= ~infinipath_hwe_htclnkabyte1crcerr;	/* don't look at crc lane1 if 8 bit */	if (dd->ipath_flags & IPATH_8BIT_IN_HT1)		val &= ~infinipath_hwe_htclnkbbyte1crcerr;	/*	 * disable RXDSYNCMEMPARITY because external serdes is unused,	 * and therefore the logic will never be used or initialized,	 * and uninitialized state will normally result in this error	 * being asserted.  Similarly for the external serdess pll	 * lock signal.	 */	val &= ~(INFINIPATH_HWE_SERDESPLLFAILED |		 INFINIPATH_HWE_RXDSYNCMEMPARITYERR);	/*	 * Disable MISCERR4 because of an inversion in the HT core	 * logic checking for errors that cause this bit to be set.	 * The errata can also cause the protocol error bit to be set	 * in the HT config space linkerror register(s).	 */	val &= ~INFINIPATH_HWE_HTCMISCERR4;	/*	 * PLL ignored because MDIO interface has a logic problem	 * for reads, on Comstock and Ponderosa.  BRINGUP	 */	if (dd->ipath_boardrev == 4 || dd->ipath_boardrev == 9)		val &= ~INFINIPATH_HWE_SERDESPLLFAILED;	dd->ipath_hwerrmask = val;}/** * ipath_ht_bringup_serdes - bring up the serdes * @dd: the infinipath device */static int ipath_ht_bringup_serdes(struct ipath_devdata *dd){	u64 val, config1;	int ret = 0, change = 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);

⌨️ 快捷键说明

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