static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr,
			    void *buffer, void *__ci)
{
	struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
	int i, error;

	for (i = 1; ; i++) {
		error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
				  buffer, 4);
		if (!error) {
			ci->speed_unverified = 0;
			break;
		}
		/* Give up after 3rd failure. */
		if (i == 3)
			break;

		/* The ieee1394_core guessed the node's speed capability from
		 * the self ID.  Check whether a lower speed works. */
		if (ci->speed_unverified) {
			error = nodemgr_check_speed(ci, addr, buffer);
			if (!error)
				break;
		}
		if (msleep_interruptible(334))
			return -EINTR;
	}
	return error;
}
static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
			       quadlet_t *buffer)
{
	quadlet_t q;
	u8 i, *speed, old_speed, good_speed;
	int error;

	speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]);
	old_speed = *speed;
	good_speed = IEEE1394_SPEED_MAX + 1;

	/* Try every speed from S100 to old_speed.
	 * If we did it the other way around, a too low speed could be caught
	 * if the retry succeeded for some other reason, e.g. because the link
	 * just finished its initialization. */
	for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
		*speed = i;
		error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
				  &q, 4);
		if (error)
			break;
		*buffer = q;
		good_speed = i;
	}
	if (good_speed <= IEEE1394_SPEED_MAX) {
		HPSB_DEBUG("Speed probe of node " NODE_BUS_FMT " yields %s",
			   NODE_BUS_ARGS(ci->host, ci->nodeid),
			   hpsb_speedto_str[good_speed]);
		*speed = good_speed;
		ci->speed_unverified = 0;
		return 0;
	}
	*speed = old_speed;
	return error;
}
示例#3
0
static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
                            void *buffer, void *__ci)
{
	struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
	int i, ret = 0;

	for (i = 0; i < 3; i++) {
		ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
				buffer, length);
		if (!ret)
			break;

		if (msleep_interruptible(334))
			return -EINTR;
	}

	return ret;
}