コード例 #1
0
ファイル: ipath_diag.c プロジェクト: ivucica/linux
int ipath_diag_add(struct ipath_devdata *dd)
{
	char name[16];
	int ret = 0;

	if (atomic_inc_return(&diagpkt_count) == 1) {
		ret = ipath_cdev_init(IPATH_DIAGPKT_MINOR,
				      "ipath_diagpkt", &diagpkt_file_ops,
				      &diagpkt_cdev, &diagpkt_class_dev);

		if (ret) {
			ipath_dev_err(dd, "Couldn't create ipath_diagpkt "
				      "device: %d", ret);
			goto done;
		}
	}

	snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit);

	ret = ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
			      &diag_file_ops, &dd->diag_cdev,
			      &dd->diag_class_dev);
	if (ret)
		ipath_dev_err(dd, "Couldn't create %s device: %d",
			      name, ret);

done:
	return ret;
}
コード例 #2
0
ファイル: ipath_sysfs.c プロジェクト: ManiacTwister/linux-hnd
static ssize_t store_rx_pol_inv(struct device *dev,
			  struct device_attribute *attr,
			  const char *buf,
			  size_t count)
{
	struct ipath_devdata *dd = dev_get_drvdata(dev);
	int ret, r;
	u16 val;

	ret = ipath_parse_ushort(buf, &val);
	if (ret < 0)
		goto invalid;

	r = ipath_set_rx_pol_inv(dd, val);
	if (r < 0) {
		ret = r;
		goto bail;
	}

	goto bail;
invalid:
	ipath_dev_err(dd, "attempt to set invalid Rx Polarity invert\n");
bail:
	return ret;
}
コード例 #3
0
ファイル: ipath_sysfs.c プロジェクト: ManiacTwister/linux-hnd
static ssize_t store_link_state(struct device *dev,
			 struct device_attribute *attr,
			  const char *buf,
			  size_t count)
{
	struct ipath_devdata *dd = dev_get_drvdata(dev);
	int ret, r;
	u16 state;

	ret = ipath_parse_ushort(buf, &state);
	if (ret < 0)
		goto invalid;

	r = ipath_set_linkstate(dd, state);
	if (r < 0) {
		ret = r;
		goto bail;
	}

	goto bail;
invalid:
	ipath_dev_err(dd, "attempt to set invalid link state\n");
bail:
	return ret;
}
コード例 #4
0
ファイル: ipath_sysfs.c プロジェクト: ManiacTwister/linux-hnd
static ssize_t store_lid(struct device *dev,
			 struct device_attribute *attr,
			  const char *buf,
			  size_t count)
{
	struct ipath_devdata *dd = dev_get_drvdata(dev);
	u16 lid = 0;
	int ret;

	ret = ipath_parse_ushort(buf, &lid);
	if (ret < 0)
		goto invalid;

	if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) {
		ret = -EINVAL;
		goto invalid;
	}

	ipath_set_lid(dd, lid, 0);

	goto bail;
invalid:
	ipath_dev_err(dd, "attempt to set invalid LID 0x%x\n", lid);
bail:
	return ret;
}
コード例 #5
0
ファイル: ipath_sysfs.c プロジェクト: ManiacTwister/linux-hnd
static ssize_t store_enabled(struct device *dev,
			 struct device_attribute *attr,
			  const char *buf,
			  size_t count)
{
	struct ipath_devdata *dd = dev_get_drvdata(dev);
	ssize_t ret;
	u16 enable = 0;

	ret = ipath_parse_ushort(buf, &enable);
	if (ret < 0) {
		ipath_dev_err(dd, "attempt to use non-numeric on enable\n");
		goto bail;
	}

	if (enable) {
		if (!(dd->ipath_flags & IPATH_DISABLED))
			goto bail;

		dev_info(dev, "Enabling unit %d\n", dd->ipath_unit);
		/* same as post-reset */
		ret = ipath_init_chip(dd, 1);
		if (ret)
			ipath_dev_err(dd, "Failed to enable unit %d\n",
				      dd->ipath_unit);
		else {
			dd->ipath_flags &= ~IPATH_DISABLED;
			*dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED;
		}
	}
	else if (!(dd->ipath_flags & IPATH_DISABLED)) {
		dev_info(dev, "Disabling unit %d\n", dd->ipath_unit);
		ipath_shutdown_device(dd);
		dd->ipath_flags |= IPATH_DISABLED;
		*dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED;
	}

bail:
	return ret;
}
コード例 #6
0
static ssize_t flash_read(struct file *file, char __user *buf,
			  size_t count, loff_t *ppos)
{
	struct ipath_devdata *dd;
	ssize_t ret;
	loff_t pos;
	char *tmp;

	pos = *ppos;

	if ( pos < 0) {
		ret = -EINVAL;
		goto bail;
	}

	if (pos >= sizeof(struct ipath_flash)) {
		ret = 0;
		goto bail;
	}

	if (count > sizeof(struct ipath_flash) - pos)
		count = sizeof(struct ipath_flash) - pos;

	tmp = kmalloc(count, GFP_KERNEL);
	if (!tmp) {
		ret = -ENOMEM;
		goto bail;
	}

	dd = file->f_path.dentry->d_inode->i_private;
	if (ipath_eeprom_read(dd, pos, tmp, count)) {
		ipath_dev_err(dd, "failed to read from flash\n");
		ret = -ENXIO;
		goto bail_tmp;
	}

	if (copy_to_user(buf, tmp, count)) {
		ret = -EFAULT;
		goto bail_tmp;
	}

	*ppos = pos + count;
	ret = count;

bail_tmp:
	kfree(tmp);

bail:
	return ret;
}
コード例 #7
0
static ssize_t flash_write(struct file *file, const char __user *buf,
			   size_t count, loff_t *ppos)
{
	struct ipath_devdata *dd;
	ssize_t ret;
	loff_t pos;
	char *tmp;

	pos = *ppos;

	if (pos != 0) {
		ret = -EINVAL;
		goto bail;
	}

	if (count != sizeof(struct ipath_flash)) {
		ret = -EINVAL;
		goto bail;
	}

	tmp = kmalloc(count, GFP_KERNEL);
	if (!tmp) {
		ret = -ENOMEM;
		goto bail;
	}

	if (copy_from_user(tmp, buf, count)) {
		ret = -EFAULT;
		goto bail_tmp;
	}

	dd = file->f_path.dentry->d_inode->i_private;
	if (ipath_eeprom_write(dd, pos, tmp, count)) {
		ret = -ENXIO;
		ipath_dev_err(dd, "failed to write to flash\n");
		goto bail_tmp;
	}

	*ppos = pos + count;
	ret = count;

bail_tmp:
	kfree(tmp);

bail:
	return ret;
}
コード例 #8
0
static int ipath_resync_ibepb(struct ipath_devdata *dd)
{
	int ret, pat, tries, chn;
	u32 loc;

	ret = -1;
	chn = 0;
	for (tries = 0; tries < (4 * IBSD_RESYNC_TRIES); ++tries) {
		loc = IB_PGUDP(chn);
		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
		if (ret < 0) {
			ipath_dev_err(dd, "Failed read in resync\n");
			continue;
		}
		if (ret != 0xF0 && ret != 0x55 && tries == 0)
			ipath_dev_err(dd, "unexpected pattern in resync\n");
		pat = ret ^ 0xA5; /* alternate F0 and 55 */
		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, pat, 0xFF);
		if (ret < 0) {
			ipath_dev_err(dd, "Failed write in resync\n");
			continue;
		}
		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
		if (ret < 0) {
			ipath_dev_err(dd, "Failed re-read in resync\n");
			continue;
		}
		if (ret != pat) {
			ipath_dev_err(dd, "Failed compare1 in resync\n");
			continue;
		}
		loc = IB_CMUDONE(chn);
		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
		if (ret < 0) {
			ipath_dev_err(dd, "Failed CMUDONE rd in resync\n");
			continue;
		}
		if ((ret & 0x70) != ((chn << 4) | 0x40)) {
			ipath_dev_err(dd, "Bad CMUDONE value %02X, chn %d\n",
				ret, chn);
			continue;
		}
		if (++chn == 4)
			break;  /* Success */
	}
	ipath_cdbg(VERBOSE, "Resync in %d tries\n", tries);
	return (ret > 0) ? 0 : ret;
}
コード例 #9
0
ファイル: ipath_sysfs.c プロジェクト: ManiacTwister/linux-hnd
static ssize_t store_guid(struct device *dev,
			 struct device_attribute *attr,
			  const char *buf,
			  size_t count)
{
	struct ipath_devdata *dd = dev_get_drvdata(dev);
	ssize_t ret;
	unsigned short guid[8];
	__be64 new_guid;
	u8 *ng;
	int i;

	if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
		   &guid[0], &guid[1], &guid[2], &guid[3],
		   &guid[4], &guid[5], &guid[6], &guid[7]) != 8)
		goto invalid;

	ng = (u8 *) &new_guid;

	for (i = 0; i < 8; i++) {
		if (guid[i] > 0xff)
			goto invalid;
		ng[i] = guid[i];
	}

	if (new_guid == 0)
		goto invalid;

	dd->ipath_guid = new_guid;
	dd->ipath_nguid = 1;

	ret = strlen(buf);
	goto bail;

invalid:
	ipath_dev_err(dd, "attempt to set invalid GUID\n");
	ret = -EINVAL;

bail:
	return ret;
}
コード例 #10
0
ファイル: ipath_sysfs.c プロジェクト: ManiacTwister/linux-hnd
static ssize_t store_mlid(struct device *dev,
			 struct device_attribute *attr,
			  const char *buf,
			  size_t count)
{
	struct ipath_devdata *dd = dev_get_drvdata(dev);
	u16 mlid;
	int ret;

	ret = ipath_parse_ushort(buf, &mlid);
	if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE)
		goto invalid;

	dd->ipath_mlid = mlid;

	goto bail;
invalid:
	ipath_dev_err(dd, "attempt to set invalid MLID\n");
bail:
	return ret;
}
コード例 #11
0
static ssize_t flash_write(struct file *file, const char __user *buf,
			   size_t count, loff_t *ppos)
{
	struct ipath_devdata *dd;
	ssize_t ret;
	loff_t pos;
	char *tmp;

	pos = *ppos;

	if (pos != 0) {
		ret = -EINVAL;
		goto bail;
	}

	if (count != sizeof(struct ipath_flash)) {
		ret = -EINVAL;
		goto bail;
	}

	tmp = memdup_user(buf, count);
	if (IS_ERR(tmp))
		return PTR_ERR(tmp);

	dd = file_inode(file)->i_private;
	if (ipath_eeprom_write(dd, pos, tmp, count)) {
		ret = -ENXIO;
		ipath_dev_err(dd, "failed to write to flash\n");
		goto bail_tmp;
	}

	*ppos = pos + count;
	ret = count;

bail_tmp:
	kfree(tmp);

bail:
	return ret;
}
コード例 #12
0
void ipath_sd7220_clr_ibpar(struct ipath_devdata *dd)
{
	int ret;

	/* clear, then re-enable parity errs */
	ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6,
		UC_PAR_CLR_D, UC_PAR_CLR_M);
	if (ret < 0) {
		ipath_dev_err(dd, "Failed clearing IBSerDes Parity err\n");
		goto bail;
	}
	ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0,
		UC_PAR_CLR_M);

	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
	udelay(4);
	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
		INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
bail:
	return;
}
コード例 #13
0
ファイル: ipath_sysfs.c プロジェクト: ManiacTwister/linux-hnd
static ssize_t store_mtu(struct device *dev,
			 struct device_attribute *attr,
			  const char *buf,
			  size_t count)
{
	struct ipath_devdata *dd = dev_get_drvdata(dev);
	ssize_t ret;
	u16 mtu = 0;
	int r;

	ret = ipath_parse_ushort(buf, &mtu);
	if (ret < 0)
		goto invalid;

	r = ipath_set_mtu(dd, mtu);
	if (r < 0)
		ret = r;

	goto bail;
invalid:
	ipath_dev_err(dd, "attempt to set invalid MTU\n");
bail:
	return ret;
}
コード例 #14
0
/**
 * ipath_get_faststats - get word counters from chip before they overflow
 * @opaque - contains a pointer to the infinipath device ipath_devdata
 *
 * called from add_timer
 */
void ipath_get_faststats(unsigned long opaque)
{
	struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
	u32 val;
	static unsigned cnt;

	/*
	 * don't access the chip while running diags, or memory diags can
	 * fail
	 */
	if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT) ||
	    ipath_diag_inuse)
		/* but re-arm the timer, for diags case; won't hurt other */
		goto done;

	if (dd->ipath_flags & IPATH_32BITCOUNTERS) {
		ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
		ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
	}

	ipath_qcheck(dd);

	/*
	 * deal with repeat error suppression.  Doesn't really matter if
	 * last error was almost a full interval ago, or just a few usecs
	 * ago; still won't get more than 2 per interval.  We may want
	 * longer intervals for this eventually, could do with mod, counter
	 * or separate timer.  Also see code in ipath_handle_errors() and
	 * ipath_handle_hwerrors().
	 */

	if (dd->ipath_lasterror)
		dd->ipath_lasterror = 0;
	if (dd->ipath_lasthwerror)
		dd->ipath_lasthwerror = 0;
	if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs)
	    && time_after(jiffies, dd->ipath_unmasktime)) {
		char ebuf[256];
		ipath_decode_err(ebuf, sizeof ebuf,
				 (dd->ipath_maskederrs & ~dd->
				  ipath_ignorederrs));
		if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &
		    ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
			ipath_dev_err(dd, "Re-enabling masked errors "
				      "(%s)\n", ebuf);
		else {
			/*
			 * rcvegrfull and rcvhdrqfull are "normal", for some
			 * types of processes (mostly benchmarks) that send
			 * huge numbers of messages, while not processing
			 * them.  So only complain about these at debug
			 * level.
			 */
			ipath_dbg("Disabling frequent queue full errors "
				  "(%s)\n", ebuf);
		}
		dd->ipath_maskederrs = dd->ipath_ignorederrs;
		ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
				 ~dd->ipath_maskederrs);
	}

	/* limit qfull messages to ~one per minute per port */
	if ((++cnt & 0x10)) {
		for (val = dd->ipath_cfgports - 1; ((int)val) >= 0;
		     val--) {
			if (dd->ipath_lastegrheads[val] != -1)
				dd->ipath_lastegrheads[val] = -1;
			if (dd->ipath_lastrcvhdrqtails[val] != -1)
				dd->ipath_lastrcvhdrqtails[val] = -1;
		}
	}

	if (dd->ipath_nosma_bufs) {
		dd->ipath_nosma_secs += 5;
		if (dd->ipath_nosma_secs >= 30) {
			ipath_cdbg(SMA, "No SMA bufs avail %u seconds; "
				   "cancelling pending sends\n",
				   dd->ipath_nosma_secs);
			/*
			 * issue an abort as well, in case we have a packet
			 * stuck in launch fifo.  This could corrupt an
			 * outgoing user packet in the worst case,
			 * but this is a pretty catastrophic, anyway.
			 */
			ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
					 INFINIPATH_S_ABORT);
			ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
					     dd->ipath_piobcnt2k +
					     dd->ipath_piobcnt4k -
					     dd->ipath_lastport_piobuf);
			/* start again, if necessary */
			dd->ipath_nosma_secs = 0;
		} else
			ipath_cdbg(SMA, "No SMA bufs avail %u tries, "
				   "after %u seconds\n",
				   dd->ipath_nosma_bufs,
				   dd->ipath_nosma_secs);
	}

done:
	mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5);
}
コード例 #15
0
ファイル: ipath_stats.c プロジェクト: cilynx/dd-wrt
u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
{
	u32 val, reg64 = 0;
	u64 val64;
	unsigned long t0, t1;
	u64 ret;
	unsigned long flags;

	t0 = jiffies;
	/* If fast increment counters are only 32 bits, snapshot them,
	 * and maintain them as 64bit values in the driver */
	if (!(dd->ipath_flags & IPATH_32BITCOUNTERS) &&
	    (creg == dd->ipath_cregs->cr_wordsendcnt ||
	     creg == dd->ipath_cregs->cr_wordrcvcnt ||
	     creg == dd->ipath_cregs->cr_pktsendcnt ||
	     creg == dd->ipath_cregs->cr_pktrcvcnt)) {
		val64 = ipath_read_creg(dd, creg);
		val = val64 == ~0ULL ? ~0U : 0;
		reg64 = 1;
	} else			/* val64 just to keep gcc quiet... */
		val64 = val = ipath_read_creg32(dd, creg);
	/*
	 * See if a second has passed.  This is just a way to detect things
	 * that are quite broken.  Normally this should take just a few
	 * cycles (the check is for long enough that we don't care if we get
	 * pre-empted.)  An Opteron HT O read timeout is 4 seconds with
	 * normal NB values
	 */
	t1 = jiffies;
	if (time_before(t0 + HZ, t1) && val == -1) {
		ipath_dev_err(dd, "Error!  Read counter 0x%x timed out\n",
			      creg);
		ret = 0ULL;
		goto bail;
	}
	if (reg64) {
		ret = val64;
		goto bail;
	}

	if (creg == dd->ipath_cregs->cr_wordsendcnt) {
		if (val != dd->ipath_lastsword) {
			dd->ipath_sword += val - dd->ipath_lastsword;
			spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
			dd->ipath_traffic_wds += val - dd->ipath_lastsword;
			spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
			dd->ipath_lastsword = val;
		}
		val64 = dd->ipath_sword;
	} else if (creg == dd->ipath_cregs->cr_wordrcvcnt) {
		if (val != dd->ipath_lastrword) {
			dd->ipath_rword += val - dd->ipath_lastrword;
			spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
			dd->ipath_traffic_wds += val - dd->ipath_lastrword;
			spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
			dd->ipath_lastrword = val;
		}
		val64 = dd->ipath_rword;
	} else if (creg == dd->ipath_cregs->cr_pktsendcnt) {
		if (val != dd->ipath_lastspkts) {
			dd->ipath_spkts += val - dd->ipath_lastspkts;
			dd->ipath_lastspkts = val;
		}
		val64 = dd->ipath_spkts;
	} else if (creg == dd->ipath_cregs->cr_pktrcvcnt) {
		if (val != dd->ipath_lastrpkts) {
			dd->ipath_rpkts += val - dd->ipath_lastrpkts;
			dd->ipath_lastrpkts = val;
		}
		val64 = dd->ipath_rpkts;
	} else
		val64 = (u64) val;

	ret = val64;

bail:
	return ret;
}
コード例 #16
0
ファイル: ipath_stats.c プロジェクト: cilynx/dd-wrt
/**
 * ipath_get_faststats - get word counters from chip before they overflow
 * @opaque - contains a pointer to the infinipath device ipath_devdata
 *
 * called from add_timer
 */
void ipath_get_faststats(unsigned long opaque)
{
	struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
	u32 val;
	static unsigned cnt;
	unsigned long flags;

	/*
	 * don't access the chip while running diags, or memory diags can
	 * fail
	 */
	if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_INITTED) ||
	    ipath_diag_inuse)
		/* but re-arm the timer, for diags case; won't hurt other */
		goto done;

	/*
	 * We now try to maintain a "active timer", based on traffic
	 * exceeding a threshold, so we need to check the word-counts
	 * even if they are 64-bit.
	 */
	ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
	ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
	spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
	if (dd->ipath_traffic_wds  >= IPATH_TRAFFIC_ACTIVE_THRESHOLD)
		atomic_add(5, &dd->ipath_active_time); /* S/B #define */
	dd->ipath_traffic_wds = 0;
	spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);

	if (dd->ipath_flags & IPATH_32BITCOUNTERS) {
		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
	}

	ipath_qcheck(dd);

	/*
	 * deal with repeat error suppression.  Doesn't really matter if
	 * last error was almost a full interval ago, or just a few usecs
	 * ago; still won't get more than 2 per interval.  We may want
	 * longer intervals for this eventually, could do with mod, counter
	 * or separate timer.  Also see code in ipath_handle_errors() and
	 * ipath_handle_hwerrors().
	 */

	if (dd->ipath_lasterror)
		dd->ipath_lasterror = 0;
	if (dd->ipath_lasthwerror)
		dd->ipath_lasthwerror = 0;
	if (dd->ipath_maskederrs
	    && time_after(jiffies, dd->ipath_unmasktime)) {
		char ebuf[256];
		int iserr;
		iserr = ipath_decode_err(ebuf, sizeof ebuf,
			dd->ipath_maskederrs);
		if (dd->ipath_maskederrs &
				~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
				INFINIPATH_E_PKTERRS ))
			ipath_dev_err(dd, "Re-enabling masked errors "
				      "(%s)\n", ebuf);
		else {
			/*
			 * rcvegrfull and rcvhdrqfull are "normal", for some
			 * types of processes (mostly benchmarks) that send
			 * huge numbers of messages, while not processing
			 * them.  So only complain about these at debug
			 * level.
			 */
			if (iserr)
					ipath_dbg("Re-enabling queue full errors (%s)\n",
							ebuf);
			else
				ipath_cdbg(ERRPKT, "Re-enabling packet"
						" problem interrupt (%s)\n", ebuf);
		}

		/* re-enable masked errors */
		dd->ipath_errormask |= dd->ipath_maskederrs;
		ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
			dd->ipath_errormask);
		dd->ipath_maskederrs = 0;
	}

	/* limit qfull messages to ~one per minute per port */
	if ((++cnt & 0x10)) {
		for (val = dd->ipath_cfgports - 1; ((int)val) >= 0;
		     val--) {
			if (dd->ipath_lastegrheads[val] != -1)
				dd->ipath_lastegrheads[val] = -1;
			if (dd->ipath_lastrcvhdrqtails[val] != -1)
				dd->ipath_lastrcvhdrqtails[val] = -1;
		}
	}

	ipath_chk_errormask(dd);
done:
	mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5);
}
コード例 #17
0
/*
 * Localize the stuff that should be done to change IB uC reset
 * returns <0 for errors.
 */
static int ipath_ibsd_reset(struct ipath_devdata *dd, int assert_rst)
{
	u64 rst_val;
	int ret = 0;
	unsigned long flags;

	rst_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibserdesctrl);
	if (assert_rst) {
		/*
		 * Vendor recommends "interrupting" uC before reset, to
		 * minimize possible glitches.
		 */
		spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
		epb_access(dd, IB_7220_SERDES, 1);
		rst_val |= 1ULL;
		/* Squelch possible parity error from _asserting_ reset */
		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
			dd->ipath_hwerrmask &
			~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val);
		/* flush write, delay to ensure it took effect */
		ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
		udelay(2);
		/* once it's reset, can remove interrupt */
		epb_access(dd, IB_7220_SERDES, -1);
		spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
	} else {
		/*
		 * Before we de-assert reset, we need to deal with
		 * possible glitch on the Parity-error line.
		 * Suppress it around the reset, both in chip-level
		 * hwerrmask and in IB uC control reg. uC will allow
		 * it again during startup.
		 */
		u64 val;
		rst_val &= ~(1ULL);
		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
			dd->ipath_hwerrmask &
			~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);

		ret = ipath_resync_ibepb(dd);
		if (ret < 0)
			ipath_dev_err(dd, "unable to re-sync IB EPB\n");

		/* set uC control regs to suppress parity errs */
		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG5, 1, 1);
		if (ret < 0)
			goto bail;
		/* IB uC code past Version 1.32.17 allow suppression of wdog */
		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80,
			0x80);
		if (ret < 0) {
			ipath_dev_err(dd, "Failed to set WDOG disable\n");
			goto bail;
		}
		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val);
		/* flush write, delay for startup */
		ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
		udelay(1);
		/* clear, then re-enable parity errs */
		ipath_sd7220_clr_ibpar(dd);
		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
		if (val & INFINIPATH_HWE_IB_UC_MEMORYPARITYERR) {
			ipath_dev_err(dd, "IBUC Parity still set after RST\n");
			dd->ipath_hwerrmask &=
				~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR;
		}
		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
			dd->ipath_hwerrmask);
	}

bail:
	return ret;
}
コード例 #18
0
/*
 * Below is portion of IBA7220-specific bringup_serdes() that actually
 * deals with registers and memory within the SerDes itself.
 * Post IB uC code version 1.32.17, was_reset being 1 is not really
 * informative, so we double-check.
 */
int ipath_sd7220_init(struct ipath_devdata *dd, int was_reset)
{
	int ret = 1; /* default to failure */
	int first_reset;
	int val_stat;

	if (!was_reset) {
		/* entered with reset not asserted, we need to do it */
		ipath_ibsd_reset(dd, 1);
		ipath_sd_trimdone_monitor(dd, "Driver-reload");
	}

	/* Substitute our deduced value for was_reset */
	ret = ipath_ibsd_ucode_loaded(dd);
	if (ret < 0) {
		ret = 1;
		goto done;
	}
	first_reset = !ret; /* First reset if IBSD uCode not yet loaded */

	/*
	 * Alter some regs per vendor latest doc, reset-defaults
	 * are not right for IB.
	 */
	ret = ipath_sd_early(dd);
	if (ret < 0) {
		ipath_dev_err(dd, "Failed to set IB SERDES early defaults\n");
		ret = 1;
		goto done;
	}

	/*
	 * Set DAC manual trim IB.
	 * We only do this once after chip has been reset (usually
	 * same as once per system boot).
	 */
	if (first_reset) {
		ret = ipath_sd_dactrim(dd);
		if (ret < 0) {
			ipath_dev_err(dd, "Failed IB SERDES DAC trim\n");
			ret = 1;
			goto done;
		}
	}

	/*
	 * Set various registers (DDS and RXEQ) that will be
	 * controlled by IBC (in 1.2 mode) to reasonable preset values
	 * Calling the "internal" version avoids the "check for needed"
	 * and "trimdone monitor" that might be counter-productive.
	 */
	ret = ipath_internal_presets(dd);
	if (ret < 0) {
		ipath_dev_err(dd, "Failed to set IB SERDES presets\n");
		ret = 1;
		goto done;
	}
	ret = ipath_sd_trimself(dd, 0x80);
	if (ret < 0) {
		ipath_dev_err(dd, "Failed to set IB SERDES TRIMSELF\n");
		ret = 1;
		goto done;
	}

	/* Load image, then try to verify */
	ret = 0;	/* Assume success */
	if (first_reset) {
		int vfy;
		int trim_done;
		ipath_dbg("SerDes uC was reset, reloading PRAM\n");
		ret = ipath_sd7220_ib_load(dd);
		if (ret < 0) {
			ipath_dev_err(dd, "Failed to load IB SERDES image\n");
			ret = 1;
			goto done;
		}

		/* Loaded image, try to verify */
		vfy = ipath_sd7220_ib_vfy(dd);
		if (vfy != ret) {
			ipath_dev_err(dd, "SERDES PRAM VFY failed\n");
			ret = 1;
			goto done;
		}
		/*
		 * Loaded and verified. Almost good...
		 * hold "success" in ret
		 */
		ret = 0;

		/*
		 * Prev steps all worked, continue bringup
		 * De-assert RESET to uC, only in first reset, to allow
		 * trimming.
		 *
		 * Since our default setup sets START_EQ1 to
		 * PRESET, we need to clear that for this very first run.
		 */
		ret = ibsd_mod_allchnls(dd, START_EQ1(0), 0, 0x38);
		if (ret < 0) {
			ipath_dev_err(dd, "Failed clearing START_EQ1\n");
			ret = 1;
			goto done;
		}

		ipath_ibsd_reset(dd, 0);
		/*
		 * If this is not the first reset, trimdone should be set
		 * already.
		 */
		trim_done = ipath_sd_trimdone_poll(dd);
		/*
		 * Whether or not trimdone succeeded, we need to put the
		 * uC back into reset to avoid a possible fight with the
		 * IBC state-machine.
		 */
		ipath_ibsd_reset(dd, 1);

		if (!trim_done) {
			ipath_dev_err(dd, "No TRIMDONE seen\n");
			ret = 1;
			goto done;
		}

		ipath_sd_trimdone_monitor(dd, "First-reset");
		/* Remember so we do not re-do the load, dactrim, etc. */
		dd->serdes_first_init_done = 1;
	}
	/*
	 * Setup for channel training and load values for
	 * RxEq and DDS in tables used by IBC in IB1.2 mode
	 */

	val_stat = ipath_sd_setvals(dd);
	if (val_stat < 0)
		ret = 1;
done:
	/* start relock timer regardless, but start at 1 second */
	ipath_set_relock_poll(dd, -1);
	return ret;
}
コード例 #19
0
static void ipath_sd_trimdone_monitor(struct ipath_devdata *dd,
       const char *where)
{
	int ret, chn, baduns;
	u64 val;

	if (!where)
		where = "?";

	/* give time for reset to settle out in EPB */
	udelay(2);

	ret = ipath_resync_ibepb(dd);
	if (ret < 0)
		ipath_dev_err(dd, "not able to re-sync IB EPB (%s)\n", where);

	/* Do "sacrificial read" to get EPB in sane state after reset */
	ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(0), 0, 0);
	if (ret < 0)
		ipath_dev_err(dd, "Failed TRIMDONE 1st read, (%s)\n", where);

	/* Check/show "summary" Trim-done bit in IBCStatus */
	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
	if (val & (1ULL << 11))
		ipath_cdbg(VERBOSE, "IBCS TRIMDONE set (%s)\n", where);
	else
		ipath_dev_err(dd, "IBCS TRIMDONE clear (%s)\n", where);

	udelay(2);

	ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80);
	if (ret < 0)
		ipath_dev_err(dd, "Failed Dummy RMW, (%s)\n", where);
	udelay(10);

	baduns = 0;

	for (chn = 3; chn >= 0; --chn) {
		/* Read CTRL reg for each channel to check TRIMDONE */
		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
			IB_CTRL2(chn), 0, 0);
		if (ret < 0)
			ipath_dev_err(dd, "Failed checking TRIMDONE, chn %d"
				" (%s)\n", chn, where);

		if (!(ret & 0x10)) {
			int probe;
			baduns |= (1 << chn);
			ipath_dev_err(dd, "TRIMDONE cleared on chn %d (%02X)."
				" (%s)\n", chn, ret, where);
			probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
				IB_PGUDP(0), 0, 0);
			ipath_dev_err(dd, "probe is %d (%02X)\n",
				probe, probe);
			probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
				IB_CTRL2(chn), 0, 0);
			ipath_dev_err(dd, "re-read: %d (%02X)\n",
				probe, probe);
			ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
				IB_CTRL2(chn), 0x10, 0x10);
			if (ret < 0)
				ipath_dev_err(dd,
					"Err on TRIMDONE rewrite1\n");
		}
	}
	for (chn = 3; chn >= 0; --chn) {
		/* Read CTRL reg for each channel to check TRIMDONE */
		if (baduns & (1 << chn)) {
			ipath_dev_err(dd,
				"Reseting TRIMDONE on chn %d (%s)\n",
				chn, where);
			ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
				IB_CTRL2(chn), 0x10, 0x10);
			if (ret < 0)
				ipath_dev_err(dd, "Failed re-setting "
					"TRIMDONE, chn %d (%s)\n",
					chn, where);
		}
	}
}