summaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2008-07-12 14:50:06 +0200
committerStefan Richter <stefanr@s5r6.in-berlin.de>2008-07-14 13:06:04 +0200
commite9aeb46c93a8b1b703d00586c05d9a71aa7e0f0c (patch)
tree8e20402235bdcdf0e250e90ba02ac9f5eae2b87c /drivers/firewire
parentfirewire: fix race of bus reset with request transmission (diff)
downloadlinux-e9aeb46c93a8b1b703d00586c05d9a71aa7e0f0c.tar.xz
linux-e9aeb46c93a8b1b703d00586c05d9a71aa7e0f0c.zip
firewire: fully initialize fw_transaction before marking it pending
In theory, card->flush_timer could already access a transaction between fw_send_request()'s spin_unlock_irqrestore and the rest of what happens in fw_send_request(). This would happen if the process which sends the request is preempted and put to sleep right after spin_unlock_irqrestore for longer than 100ms. Therefore we fill in everything in struct fw_transaction at which the flush_timer might look at before we lift the lock. To do: Ensure that the timer does not pick up the transaction before the time of the AT request event plus split transaction timeout. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/fw-transaction.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index 40db80752272..7addfb3b070b 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -279,11 +279,6 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
card->tlabel_mask |= (1 << tlabel);
- list_add_tail(&t->link, &card->transaction_list);
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- /* Initialize rest of transaction, fill out packet and send it. */
t->node_id = node_id;
t->tlabel = tlabel;
t->callback = callback;
@@ -294,6 +289,10 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
speed, offset, payload, length);
t->packet.callback = transmit_complete_callback;
+ list_add_tail(&t->link, &card->transaction_list);
+
+ spin_unlock_irqrestore(&card->lock, flags);
+
card->driver->send_request(card, &t->packet);
}
EXPORT_SYMBOL(fw_send_request);