/** * @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),;);
/** * 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; } }