/**
 * @ingroup trans
 * @anchor hpsb_get_tlabel
 * allocate a transaction label
 *
 * 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).
 *
 * @param packet - the packet who's tlabel/tpool we set
 * @return  Zero on success, otherwise non-zero. A non-zero return
 * generally means there are no available tlabels. 
 */
int hpsb_get_tlabel(struct hpsb_packet *packet)
{
	unsigned long flags;
	struct hpsb_tlabel_pool *tp;

	tp = &packet->host->tpool[packet->node_id & NODE_MASK];

	//~ if (irqs_disabled() || in_atomic()) {
	//~ if(in_interrupt()) {
		//~ if (down_trylock(&tp->count))
			//~ return 1;
	//~ } else {
		//~ down(&tp->count);
	//~ }
	//~ rtos_res_lock(&tp->count); //64 tasks can call here without blocking
	if(atomic_read(&tp->count)<0) {
		HPSB_ERR("run out of tlabel\n");
		return 1;
	}
	atomic_dec(&tp->count);

	rtos_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 */
	RTOS_ASSERT(!test_and_set_bit(packet->tlabel, tp->pool),;);
예제 #2
0
/**
 * hpsb_packet_success - Make sense of the ack and reply codes
 *
 * Make sense of the ack and reply codes and return more convenient error codes:
 * 0 = success.  -%EBUSY = node is busy, try again.  -%EAGAIN = error which can
 * probably resolved by retry.  -%EREMOTEIO = node suffers from an internal
 * error.  -%EACCES = this transaction is not allowed on requested address.
 * -%EINVAL = invalid address at node.
 */
int hpsb_packet_success(struct hpsb_packet *packet)
{
	switch (packet->ack_code) {
	case ACK_PENDING:
		switch ((packet->header[1] >> 12) & 0xf) {
		case RCODE_COMPLETE:
			return 0;
		case RCODE_CONFLICT_ERROR:
			return -EAGAIN;
		case RCODE_DATA_ERROR:
			return -EREMOTEIO;
		case RCODE_TYPE_ERROR:
			return -EACCES;
		case RCODE_ADDRESS_ERROR:
			return -EINVAL;
		default:
			HPSB_ERR("received reserved rcode %d from node %d",
				 (packet->header[1] >> 12) & 0xf,
				 packet->node_id);
			return -EAGAIN;
		}

	case ACK_BUSY_X:
	case ACK_BUSY_A:
	case ACK_BUSY_B:
		return -EBUSY;

	case ACK_TYPE_ERROR:
		return -EACCES;

	case ACK_COMPLETE:
		if (packet->tcode == TCODE_WRITEQ
		    || packet->tcode == TCODE_WRITEB) {
			return 0;
		} else {
			HPSB_ERR("impossible ack_complete from node %d "
				 "(tcode %d)", packet->node_id, packet->tcode);
			return -EAGAIN;
		}

	case ACK_DATA_ERROR:
		if (packet->tcode == TCODE_WRITEB
		    || packet->tcode == TCODE_LOCK_REQUEST) {
			return -EAGAIN;
		} else {
			HPSB_ERR("impossible ack_data_error from node %d "
				 "(tcode %d)", packet->node_id, packet->tcode);
			return -EAGAIN;
		}

	case ACK_ADDRESS_ERROR:
		return -EINVAL;

	case ACK_TARDY:
	case ACK_CONFLICT_ERROR:
	case ACKX_NONE:
	case ACKX_SEND_ERROR:
	case ACKX_ABORTED:
	case ACKX_TIMEOUT:
		/* error while sending */
		return -EAGAIN;

	default:
		HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
			 packet->ack_code, packet->node_id, packet->tcode);
		return -EAGAIN;
	}
}