Ejemplo n.º 1
0
/* same as hpsb_get_tlabel, except that it returns immediately */
static int hpsb_get_tlabel_atomic(struct hpsb_packet *packet)
{
	unsigned long flags, *tp;
	u8 *next;
	int tlabel, n = NODEID_TO_NODE(packet->node_id);

	/* Broadcast transactions are complete once the request has been sent.
	 * Use the same transaction label for all broadcast transactions. */
	if (unlikely(n == ALL_NODES)) {
		packet->tlabel = 0;
		return 0;
	}
	tp = packet->host->tl_pool[n].map;
	next = &packet->host->next_tl[n];

	spin_lock_irqsave(&hpsb_tlabel_lock, flags);
	tlabel = find_next_zero_bit(tp, 64, *next);
	if (tlabel > 63)
		tlabel = find_first_zero_bit(tp, 64);
	if (tlabel > 63) {
		spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
		return -EAGAIN;
	}
	__set_bit(tlabel, tp);
	*next = (tlabel + 1) & 63;
	spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);

	packet->tlabel = tlabel;
	return 0;
}
/**
 * hpsb_get_tlabel - allocate a transaction label
 * @packet: the packet who's tlabel/tpool we set
 *
 * Every asynchronous transaction on the 1394 bus needs a transaction
 * label to match the response to the request.  This label has to be
 * different from any other transaction label in an outstanding request to
 * the same node to make matching possible without ambiguity.
 *
 * There are 64 different tlabels, so an allocated tlabel has to be freed
 * with hpsb_free_tlabel() after the transaction is complete (unless it's
 * reused again for the same target node).
 *
 * Return value: Zero on success, otherwise non-zero. A non-zero return
 * generally means there are no available tlabels. If this is called out
 * of interrupt or atomic context, then it will sleep until can return a
 * tlabel.
 */
int hpsb_get_tlabel(struct hpsb_packet *packet)
{
	unsigned long flags;
	struct hpsb_tlabel_pool *tp;
	int n = NODEID_TO_NODE(packet->node_id);

	if (unlikely(n == ALL_NODES))
		return 0;
	tp = &packet->host->tpool[n];

	if (irqs_disabled() || in_atomic()) {
		if (down_trylock(&tp->count))
			return 1;
	} else {
		down(&tp->count);
	}

	spin_lock_irqsave(&tp->lock, flags);

	packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next);
	if (packet->tlabel > 63)
		packet->tlabel = find_first_zero_bit(tp->pool, 64);
	tp->next = (packet->tlabel + 1) % 64;
	/* Should _never_ happen */
	BUG_ON(test_and_set_bit(packet->tlabel, tp->pool));
	tp->allocations++;
	spin_unlock_irqrestore(&tp->lock, flags);

	return 0;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
/**
 * hpsb_free_tlabel - free an allocated transaction label
 * @packet: packet whose tlabel and tl_pool needs to be cleared
 *
 * Frees the transaction label allocated with hpsb_get_tlabel().  The
 * tlabel has to be freed after the transaction is complete (i.e. response
 * was received for a split transaction or packet was sent for a unified
 * transaction).
 *
 * A tlabel must not be freed twice.
 */
void hpsb_free_tlabel(struct hpsb_packet *packet)
{
	unsigned long flags, *tp;
	int tlabel, n = NODEID_TO_NODE(packet->node_id);

	if (unlikely(n == ALL_NODES))
		return;
	tp = packet->host->tl_pool[n].map;
	tlabel = packet->tlabel;
	BUG_ON(tlabel > 63 || tlabel < 0);

	spin_lock_irqsave(&hpsb_tlabel_lock, flags);
	BUG_ON(!__test_and_clear_bit(tlabel, tp));
	spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);

	wake_up_interruptible(&tlabel_wq);
}
/**
 * hpsb_free_tlabel - free an allocated transaction label
 * @packet: packet whos tlabel/tpool needs to be cleared
 *
 * Frees the transaction label allocated with hpsb_get_tlabel().  The
 * tlabel has to be freed after the transaction is complete (i.e. response
 * was received for a split transaction or packet was sent for a unified
 * transaction).
 *
 * A tlabel must not be freed twice.
 */
void hpsb_free_tlabel(struct hpsb_packet *packet)
{
	unsigned long flags;
	struct hpsb_tlabel_pool *tp;
	int n = NODEID_TO_NODE(packet->node_id);

	if (unlikely(n == ALL_NODES))
		return;
	tp = &packet->host->tpool[n];

	BUG_ON(packet->tlabel > 63 || packet->tlabel < 0);

	spin_lock_irqsave(&tp->lock, flags);
	BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool));
	spin_unlock_irqrestore(&tp->lock, flags);

	up(&tp->count);
}