forked from luck/tmp_suning_uos_patched
firewire: core: make transaction label allocation more robust
If one request is so long-lived that it does not get a response before the following 63 requests, its bit in tlabel_mask is still set when the next request tries to allocate a transaction label for that number. In this state, while the first request is not completed or timed out, no new requests can be submitted. To fix this, skip over any label still in use, and do not error out unless we have entirely run out of labels. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
parent
edd5bdaf12
commit
7906054f0d
@ -229,6 +229,23 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
|
|||||||
packet->payload_mapped = false;
|
packet->payload_mapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int allocate_tlabel(struct fw_card *card)
|
||||||
|
{
|
||||||
|
int tlabel;
|
||||||
|
|
||||||
|
tlabel = card->current_tlabel;
|
||||||
|
while (card->tlabel_mask & (1ULL << tlabel)) {
|
||||||
|
tlabel = (tlabel + 1) & 0x3f;
|
||||||
|
if (tlabel == card->current_tlabel)
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
card->current_tlabel = (tlabel + 1) & 0x3f;
|
||||||
|
card->tlabel_mask |= 1ULL << tlabel;
|
||||||
|
|
||||||
|
return tlabel;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function provides low-level access to the IEEE1394 transaction
|
* This function provides low-level access to the IEEE1394 transaction
|
||||||
* logic. Most C programs would use either fw_read(), fw_write() or
|
* logic. Most C programs would use either fw_read(), fw_write() or
|
||||||
@ -290,16 +307,13 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
|
|||||||
|
|
||||||
spin_lock_irqsave(&card->lock, flags);
|
spin_lock_irqsave(&card->lock, flags);
|
||||||
|
|
||||||
tlabel = card->current_tlabel;
|
tlabel = allocate_tlabel(card);
|
||||||
if (card->tlabel_mask & (1ULL << tlabel)) {
|
if (tlabel < 0) {
|
||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data);
|
callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
card->current_tlabel = (card->current_tlabel + 1) & 0x3f;
|
|
||||||
card->tlabel_mask |= (1ULL << tlabel);
|
|
||||||
|
|
||||||
t->node_id = destination_id;
|
t->node_id = destination_id;
|
||||||
t->tlabel = tlabel;
|
t->tlabel = tlabel;
|
||||||
t->callback = callback;
|
t->callback = callback;
|
||||||
|
Loading…
Reference in New Issue
Block a user