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

📄 ipath_iba6120.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
			ipath_dbg("Never got MDIO data for XGXS "				  "status read\n");		else			ipath_cdbg(VERBOSE, "MDIO Read reg8, "				   "'bank' 31 %x\n", (u32) val);	} else		ipath_dbg("Never got MDIO cmdready for XGXS status read\n");	return ret;}/** * ipath_pe_quiet_serdes - set serdes to txidle * @dd: the infinipath device * Called when driver is being unloaded */static void ipath_pe_quiet_serdes(struct ipath_devdata *dd){	u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);	val |= INFINIPATH_SERDC0_TXIDLE;	ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n",		  (unsigned long long) val);	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);}static int ipath_pe_intconfig(struct ipath_devdata *dd){	u32 chiprev;	/*	 * If the chip supports added error indication via GPIO pins,	 * enable interrupts on those bits so the interrupt routine	 * can count the events. Also set flag so interrupt routine	 * can know they are expected.	 */	chiprev = dd->ipath_revision >> INFINIPATH_R_CHIPREVMINOR_SHIFT;	if ((chiprev & INFINIPATH_R_CHIPREVMINOR_MASK) > 1) {		/* Rev2+ reports extra errors via internal GPIO pins */		dd->ipath_flags |= IPATH_GPIO_ERRINTRS;		dd->ipath_gpio_mask |= IPATH_GPIO_ERRINTR_MASK;		ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,				 dd->ipath_gpio_mask);	}	return 0;}/** * ipath_setup_pe_setextled - set the state of the two external LEDs * @dd: the infinipath device * @lst: the L state * @ltst: the LT state * These LEDs indicate the physical and logical state of IB link. * For this chip (at least with recommended board pinouts), LED1 * is Yellow (logical state) and LED2 is Green (physical 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_pe_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);	extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |				       INFINIPATH_EXTC_LED2PRIPORT_ON);	if (ltst & INFINIPATH_IBCS_LT_STATE_LINKUP)		extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;	if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)		extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;	dd->ipath_extctrl = extctl;	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);	spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);}/** * ipath_setup_pe_cleanup - clean up any per-chip chip-specific stuff * @dd: the infinipath device * * This is called during driver unload. * We do the pci_disable_msi here, not in generic code, because it * isn't used for the HT chips. If we do end up needing pci_enable_msi * at some point in the future for HT, we'll move the call back * into the main init_one code. */static void ipath_setup_pe_cleanup(struct ipath_devdata *dd){	dd->ipath_msi_lo = 0;	/* just in case unload fails */	pci_disable_msi(dd->pcidev);}/** * ipath_setup_pe_config - setup PCIe config related stuff * @dd: the infinipath device * @pdev: the PCI device * * The pci_enable_msi() call will fail on systems with MSI quirks * such as those with AMD8131, even if the device of interest is not * attached to that device, (in the 2.6.13 - 2.6.15 kernels, at least, fixed * late in 2.6.16). * All that can be done is to edit the kernel source to remove the quirk * check until that is fixed. * We do not need to call enable_msi() for our HyperTransport chip, * even though it uses MSI, and we want to avoid the quirk warning, so * So we call enable_msi only for PCIe.  If we do end up needing * pci_enable_msi at some point in the future for HT, we'll move the * call back into the main init_one code. * We save the msi lo and hi values, so we can restore them after * chip reset (the kernel PCI infrastructure doesn't yet handle that * correctly). */static int ipath_setup_pe_config(struct ipath_devdata *dd,				 struct pci_dev *pdev){	int pos, ret;	dd->ipath_msi_lo = 0;	/* used as a flag during reset processing */	ret = pci_enable_msi(dd->pcidev);	if (ret)		ipath_dev_err(dd, "pci_enable_msi failed: %d, "			      "interrupts may not work\n", ret);	/* continue even if it fails, we may still be OK... */	dd->ipath_irq = pdev->irq;	if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) {		u16 control;		pci_read_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,				      &dd->ipath_msi_lo);		pci_read_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,				      &dd->ipath_msi_hi);		pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,				     &control);		/* now save the data (vector) info */		pci_read_config_word(dd->pcidev,				     pos + ((control & PCI_MSI_FLAGS_64BIT)					    ? 12 : 8),				     &dd->ipath_msi_data);		ipath_cdbg(VERBOSE, "Read msi data 0x%x from config offset "			   "0x%x, control=0x%x\n", dd->ipath_msi_data,			   pos + ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),			   control);		/* we save the cachelinesize also, although it doesn't		 * really matter */		pci_read_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,				     &dd->ipath_pci_cacheline);	} else		ipath_dev_err(dd, "Can't find MSI capability, "			      "can't save MSI settings for reset\n");	if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP))) {		u16 linkstat;		pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,				     &linkstat);		linkstat >>= 4;		linkstat &= 0x1f;		if (linkstat != 8)			ipath_dev_err(dd, "PCIe width %u, "				      "performance reduced\n", linkstat);	}	else		ipath_dev_err(dd, "Can't find PCI Express "			      "capability!\n");	return 0;}static void ipath_init_pe_variables(struct ipath_devdata *dd){	/*	 * bits for selecting i2c direction and values,	 * used for I2C serial flash	 */	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;	/* variables for sanity checking interrupt and errors */	dd->ipath_hwe_bitsextant =		(INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<		 INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |		(INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<		 INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) |		(INFINIPATH_HWE_PCIEMEMPARITYERR_MASK <<		 INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) |		INFINIPATH_HWE_PCIE1PLLFAILED |		INFINIPATH_HWE_PCIE0PLLFAILED |		INFINIPATH_HWE_PCIEPOISONEDTLP |		INFINIPATH_HWE_PCIECPLTIMEOUT |		INFINIPATH_HWE_PCIEBUSPARITYXTLH |		INFINIPATH_HWE_PCIEBUSPARITYXADM |		INFINIPATH_HWE_PCIEBUSPARITYRADM |		INFINIPATH_HWE_MEMBISTFAILED |		INFINIPATH_HWE_COREPLL_FBSLIP |		INFINIPATH_HWE_COREPLL_RFSLIP |		INFINIPATH_HWE_SERDESPLLFAILED |		INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |		INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;	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_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;	/* Ignore errors in PIO/PBC on systems with unordered write-combining */	if (ipath_unordered_wc())		dd->ipath_eep_st_masks[0].hwerrs_to_log &= ~TXE_PIO_PARITY;	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;}/* setup the MSI stuff again after a reset.  I'd like to just call * pci_enable_msi() and request_irq() again, but when I do that, * the MSI enable bit doesn't get set in the command word, and * we switch to to a different interrupt vector, which is confusing, * so I instead just do it all inline.  Perhaps somehow can tie this * into the PCIe hotplug support at some point * Note, because I'm doing it all here, I don't call pci_disable_msi() * or free_irq() at the start of ipath_setup_pe_reset(). */static int ipath_reinit_msi(struct ipath_devdata *dd){	int pos;	u16 control;	int ret;	if (!dd->ipath_msi_lo) {		dev_info(&dd->pcidev->dev, "Can't restore MSI config, "			 "initial setup failed?\n");		ret = 0;		goto bail;	}	if (!(pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) {		ipath_dev_err(dd, "Can't find MSI capability, "			      "can't restore MSI settings\n");		ret = 0;		goto bail;	}	ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",		   dd->ipath_msi_lo, pos + PCI_MSI_ADDRESS_LO);	pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,			       dd->ipath_msi_lo);	ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",		   dd->ipath_msi_hi, pos + PCI_MSI_ADDRESS_HI);	pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,			       dd->ipath_msi_hi);	pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS, &control);	if (!(control & PCI_MSI_FLAGS_ENABLE)) {		ipath_cdbg(VERBOSE, "MSI control at off %x was %x, "			   "setting MSI enable (%x)\n", pos + PCI_MSI_FLAGS,			   control, control | PCI_MSI_FLAGS_ENABLE);		control |= PCI_MSI_FLAGS_ENABLE;		pci_write_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,				      control);	}	/* now rewrite the data (vector) info */	pci_write_config_word(dd->pcidev, pos +			      ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),			      dd->ipath_msi_data);	/* we restore the cachelinesize also, although it doesn't really	 * matter */	pci_write_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,			      dd->ipath_pci_cacheline);	/* and now set the pci master bit again */	pci_set_master(dd->pcidev);	ret = 1;bail:	return ret;}/* This routine sleeps, so it can only be called from user context, not * from interrupt context.  If we need interrupt context, we can split * it into two routines.*/static int ipath_setup_pe_reset(struct ipath_devdata *dd){	u64 val;	int i;	int ret;	/* Use ERROR so it shows up in logs, etc. */	ipath_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->ipath_unit);	/* keep chip from being accessed in a few places */	dd->ipath_flags &= ~(IPATH_INITTED|IPATH_PRESENT);	val = dd->ipath_control | INFINIPATH_C_RESET;	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, val);	mb();	for (i = 1; i <= 5; i++) {		int r;		/* allow MBIST, etc. to complete; longer on each retry.		 * We sometimes get machine checks from bus timeout if no		 * response, so for now, make it *really* long.		 */		msleep(1000 + (1 + i) * 2000);

⌨️ 快捷键说明

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