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

📄 ipath_iba6120.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		if ((r =		     pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0,					    dd->ipath_pcibar0)))			ipath_dev_err(dd, "rewrite of BAR0 failed: %d\n",				      r);		if ((r =		     pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_1,					    dd->ipath_pcibar1)))			ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n",				      r);		/* now re-enable memory access */		if ((r = pci_enable_device(dd->pcidev)))			ipath_dev_err(dd, "pci_enable_device failed after "				      "reset: %d\n", r);		/* whether it worked or not, mark as present, again */		dd->ipath_flags |= IPATH_PRESENT;		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);		if (val == dd->ipath_revision) {			ipath_cdbg(VERBOSE, "Got matching revision "				   "register %llx on try %d\n",				   (unsigned long long) val, i);			ret = ipath_reinit_msi(dd);			goto bail;		}		/* Probably getting -1 back */		ipath_dbg("Didn't get expected revision register, "			  "got %llx, try %d\n", (unsigned long long) val,			  i + 1);	}	ret = 0; /* failed */bail:	return ret;}/** * ipath_pe_put_tid - write a TID in chip * @dd: the infinipath device * @tidptr: pointer to the expected TID (in chip) to udpate * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing * * This exists as a separate routine to allow for special locking etc. * It's used for both the full cleanup on exit, as well as the normal * setup and teardown. */static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,			     u32 type, unsigned long pa){	u32 __iomem *tidp32 = (u32 __iomem *)tidptr;	unsigned long flags = 0; /* keep gcc quiet */	if (pa != dd->ipath_tidinvalid) {		if (pa & ((1U << 11) - 1)) {			dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "				 "not 4KB aligned!\n", pa);			return;		}		pa >>= 11;		/* paranoia check */		if (pa & (7<<29))			ipath_dev_err(dd,				      "BUG: Physical page address 0x%lx "				      "has bits set in 31-29\n", pa);		if (type == RCVHQ_RCV_TYPE_EAGER)			pa |= dd->ipath_tidtemplate;		else /* for now, always full 4KB page */			pa |= 2 << 29;	}	/*	 * Workaround chip bug 9437 by writing the scratch register	 * before and after the TID, and with an io write barrier.	 * We use a spinlock around the writes, so they can't intermix	 * with other TID (eager or expected) writes (the chip bug	 * is triggered by back to back TID writes). Unfortunately, this	 * call can be done from interrupt level for the port 0 eager TIDs,	 * so we have to use irqsave locks.	 */	spin_lock_irqsave(&dd->ipath_tid_lock, flags);	ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xfeeddeaf);	if (dd->ipath_kregbase)		writel(pa, tidp32);	ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xdeadbeef);	mmiowb();	spin_unlock_irqrestore(&dd->ipath_tid_lock, flags);}/** * ipath_pe_put_tid_2 - write a TID in chip, Revision 2 or higher * @dd: the infinipath device * @tidptr: pointer to the expected TID (in chip) to udpate * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing * * This exists as a separate routine to allow for selection of the * appropriate "flavor". The static calls in cleanup just use the * revision-agnostic form, as they are not performance critical. */static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,			     u32 type, unsigned long pa){	u32 __iomem *tidp32 = (u32 __iomem *)tidptr;	if (pa != dd->ipath_tidinvalid) {		if (pa & ((1U << 11) - 1)) {			dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "				 "not 2KB aligned!\n", pa);			return;		}		pa >>= 11;		/* paranoia check */		if (pa & (7<<29))			ipath_dev_err(dd,				      "BUG: Physical page address 0x%lx "				      "has bits set in 31-29\n", pa);		if (type == RCVHQ_RCV_TYPE_EAGER)			pa |= dd->ipath_tidtemplate;		else /* for now, always full 4KB page */			pa |= 2 << 29;	}	if (dd->ipath_kregbase)		writel(pa, tidp32);	mmiowb();}/** * ipath_pe_clear_tid - clear all TID entries for a port, expected and eager * @dd: the infinipath device * @port: the port * * clear all TID entries for a port, expected and eager. * Used from ipath_close().  On this chip, TIDs are only 32 bits, * not 64, but they are still on 64 bit boundaries, so tidbase * is declared as u64 * for the pointer math, even though we write 32 bits */static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port){	u64 __iomem *tidbase;	unsigned long tidinv;	int i;	if (!dd->ipath_kregbase)		return;	ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);	tidinv = dd->ipath_tidinvalid;	tidbase = (u64 __iomem *)		((char __iomem *)(dd->ipath_kregbase) +		 dd->ipath_rcvtidbase +		 port * dd->ipath_rcvtidcnt * sizeof(*tidbase));	for (i = 0; i < dd->ipath_rcvtidcnt; i++)		dd->ipath_f_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,				 tidinv);	tidbase = (u64 __iomem *)		((char __iomem *)(dd->ipath_kregbase) +		 dd->ipath_rcvegrbase +		 port * dd->ipath_rcvegrcnt * sizeof(*tidbase));	for (i = 0; i < dd->ipath_rcvegrcnt; i++)		dd->ipath_f_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER,				 tidinv);}/** * ipath_pe_tidtemplate - setup constants for TID updates * @dd: the infinipath device * * We setup stuff that we use a lot, to avoid calculating each time */static void ipath_pe_tidtemplate(struct ipath_devdata *dd){	u32 egrsize = dd->ipath_rcvegrbufsize;	/* For now, we always allocate 4KB buffers (at init) so we can	 * receive max size packets.  We may want a module parameter to	 * specify 2KB or 4KB and/or make be per port instead of per device	 * for those who want to reduce memory footprint.  Note that the	 * ipath_rcvhdrentsize size must be large enough to hold the largest	 * IB header (currently 96 bytes) that we expect to handle (plus of	 * course the 2 dwords of RHF).	 */	if (egrsize == 2048)		dd->ipath_tidtemplate = 1U << 29;	else if (egrsize == 4096)		dd->ipath_tidtemplate = 2U << 29;	else {		egrsize = 4096;		dev_info(&dd->pcidev->dev, "BUG: unsupported egrbufsize "			 "%u, using %u\n", dd->ipath_rcvegrbufsize,			 egrsize);		dd->ipath_tidtemplate = 2U << 29;	}	dd->ipath_tidinvalid = 0;}static int ipath_pe_early_init(struct ipath_devdata *dd){	dd->ipath_flags |= IPATH_4BYTE_TID;	if (ipath_unordered_wc())		dd->ipath_flags |= IPATH_PIO_FLUSH_WC;	/*	 * For openfabrics, we need to be able to handle an IB header of	 * 24 dwords.  HT chip has arbitrary sized receive buffers, so we	 * made them the same size as the PIO buffers.  This chip does not	 * handle arbitrary size buffers, so we need the header large enough	 * to handle largest IB header, but still have room for a 2KB MTU	 * standard IB packet.	 */	dd->ipath_rcvhdrentsize = 24;	dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;	/*	 * To truly support a 4KB MTU (for usermode), we need to	 * bump this to a larger value.  For now, we use them for	 * the kernel only.	 */	dd->ipath_rcvegrbufsize = 2048;	/*	 * the min() check here is currently a nop, but it may not always	 * be, depending on just how we do ipath_rcvegrbufsize	 */	dd->ipath_ibmaxlen = min(dd->ipath_piosize2k,				 dd->ipath_rcvegrbufsize +				 (dd->ipath_rcvhdrentsize << 2));	dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;	/*	 * We can request a receive interrupt for 1 or	 * more packets from current offset.  For now, we set this	 * up for a single packet.	 */	dd->ipath_rhdrhead_intr_off = 1ULL<<32;	ipath_get_eeprom_info(dd);	return 0;}int __attribute__((weak)) ipath_unordered_wc(void){	return 0;}/** * ipath_init_pe_get_base_info - set chip-specific flags for user code * @pd: the infinipath port * @kbase: ipath_base_info pointer * * We set the PCIE flag because the lower bandwidth on PCIe vs * HyperTransport can affect some user packet algorithms. */static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase){	struct ipath_base_info *kinfo = kbase;	struct ipath_devdata *dd;	if (ipath_unordered_wc()) {		kinfo->spi_runtime_flags |= IPATH_RUNTIME_FORCE_WC_ORDER;		ipath_cdbg(PROC, "Intel processor, forcing WC order\n");	}	else		ipath_cdbg(PROC, "Not Intel processor, WC ordered\n");	if (pd == NULL)		goto done;	dd = pd->port_dd;done:	kinfo->spi_runtime_flags |= IPATH_RUNTIME_PCIE |		IPATH_RUNTIME_FORCE_PIOAVAIL | IPATH_RUNTIME_PIO_REGSWAPPED;	return 0;}static void ipath_pe_free_irq(struct ipath_devdata *dd){	free_irq(dd->ipath_irq, dd);	dd->ipath_irq = 0;}/* * On platforms using this chip, and not having ordered WC stores, we * can get TXE parity errors due to speculative reads to the PIO buffers, * and this, due to a chip bug can result in (many) false parity error * reports.  So it's a debug print on those, and an info print on systems * where the speculative reads don't occur. * Because we can get lots of false errors, we have no upper limit * on recovery attempts on those platforms. */static int ipath_pe_txe_recover(struct ipath_devdata *dd){	if (ipath_unordered_wc())		ipath_dbg("Recovering from TXE PIO parity error\n");	else {		int cnt = ++ipath_stats.sps_txeparity;		if (cnt >= IPATH_MAX_PARITY_ATTEMPTS)  {			if (cnt == IPATH_MAX_PARITY_ATTEMPTS)				ipath_dev_err(dd,					"Too many attempts to recover from "					"TXE parity, giving up\n");			return 0;		}		dev_info(&dd->pcidev->dev,			"Recovering from TXE PIO parity error\n");	}	return 1;}/** * ipath_init_iba6120_funcs - set up the chip-specific function pointers * @dd: the infinipath device * * This is global, and is called directly at init to set up the * chip-specific function pointers for later use. */void ipath_init_iba6120_funcs(struct ipath_devdata *dd){	dd->ipath_f_intrsetup = ipath_pe_intconfig;	dd->ipath_f_bus = ipath_setup_pe_config;	dd->ipath_f_reset = ipath_setup_pe_reset;	dd->ipath_f_get_boardname = ipath_pe_boardname;	dd->ipath_f_init_hwerrors = ipath_pe_init_hwerrors;	dd->ipath_f_early_init = ipath_pe_early_init;	dd->ipath_f_handle_hwerrors = ipath_pe_handle_hwerrors;	dd->ipath_f_quiet_serdes = ipath_pe_quiet_serdes;	dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes;	dd->ipath_f_clear_tids = ipath_pe_clear_tids;	/*	 * this may get changed after we read the chip revision,	 * but we start with the safe version for all revs	 */	dd->ipath_f_put_tid = ipath_pe_put_tid;	dd->ipath_f_cleanup = ipath_setup_pe_cleanup;	dd->ipath_f_setextled = ipath_setup_pe_setextled;	dd->ipath_f_get_base_info = ipath_pe_get_base_info;	dd->ipath_f_free_irq = ipath_pe_free_irq;	/* initialize chip-specific variables */	dd->ipath_f_tidtemplate = ipath_pe_tidtemplate;	/*	 * setup the register offsets, since they are different for each	 * chip	 */	dd->ipath_kregs = &ipath_pe_kregs;	dd->ipath_cregs = &ipath_pe_cregs;	ipath_init_pe_variables(dd);}

⌨️ 快捷键说明

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