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