VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
author: Clemens Ladisch <clemens@ladisch.de> 2010-04-27 09:07:00 +0200 committer: Stefan Richter <stefanr@s5r6.in-berlin.de> 2010-05-19 00:26:30 +0200 commit: 5c40cbfefa828208c671e2f58789e4dd04f79563 parent: 753a8970f68594ea69c5fc13fbca18dbd9402996
Commit Summary:
firewire: core: use separate timeout for each transaction
Diffstat:
1 file changed, 34 insertions, 29 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 901669876c25..fdc33ff06dc1 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -81,7 +81,7 @@ static int close_transaction(struct fw_transaction *transaction,
 	spin_lock_irqsave(&card->lock, flags);
 	list_for_each_entry(t, &card->transaction_list, link) {
 		if (t == transaction) {
-			list_del(&t->link);
+			list_del_init(&t->link);
 			card->tlabel_mask &= ~(1ULL << t->tlabel);
 			break;
 		}
@@ -89,6 +89,7 @@ static int close_transaction(struct fw_transaction *transaction,
 	spin_unlock_irqrestore(&card->lock, flags);
 
 	if (&t->link != &card->transaction_list) {
+		del_timer_sync(&t->split_timeout_timer);
 		t->callback(card, rcode, NULL, 0, t->callback_data);
 		return 0;
 	}
@@ -121,6 +122,31 @@ int fw_cancel_transaction(struct fw_card *card,
 }
 EXPORT_SYMBOL(fw_cancel_transaction);
 
+static void split_transaction_timeout_callback(unsigned long data)
+{
+	struct fw_transaction *t = (struct fw_transaction *)data;
+	struct fw_card *card = t->card;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
+	if (list_empty(&t->link)) {
+		spin_unlock_irqrestore(&card->lock, flags);
+		return;
+	}
+	list_del(&t->link);
+	card->tlabel_mask &= ~(1ULL << t->tlabel);
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	card->driver->cancel_packet(card, &t->packet);
+
+	/*
+	 * At this point cancel_packet will never call the transaction
+	 * callback, since we just took the transaction out of the list.
+	 * So do it here.
+	 */
+	t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
+}
+
 static void transmit_complete_callback(struct fw_packet *packet,
 				       struct fw_card *card, int status)
 {
@@ -293,13 +319,6 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
 	unsigned long flags;
 	int tlabel;
 
-	/*
-	 * Bump the flush timer up 100ms first of all so we
-	 * don't race with a flush timer callback.
-	 */
-
-	mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10));
-
 	/*
 	 * Allocate tlabel from the bitmap and put the transaction on
 	 * the list while holding the card spinlock.
@@ -316,6 +335,11 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
 
 	t->node_id = destination_id;
 	t->tlabel = tlabel;
+	t->card = card;
+	setup_timer(&t->split_timeout_timer,
+		    split_transaction_timeout_callback, (unsigned long)t);
+	/* FIXME: start this timer later, relative to t->timestamp */
+	mod_timer(&t->split_timeout_timer, jiffies + DIV_ROUND_UP(HZ, 10));
 	t->callback = callback;
 	t->callback_data = callback_data;
 
@@ -361,11 +385,13 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
 	struct transaction_callback_data d;
 	struct fw_transaction t;
 
+	init_timer_on_stack(&t.split_timeout_timer);
 	init_completion(&d.done);
 	d.payload = payload;
 	fw_send_request(card, &t, tcode, destination_id, generation, speed,
 			offset, payload, length, transaction_callback, &d);
 	wait_for_completion(&d.done);
+	destroy_timer_on_stack(&t.split_timeout_timer);
 
 	return d.rcode;
 }
@@ -408,30 +434,6 @@ void fw_send_phy_config(struct fw_card *card,
 	mutex_unlock(&phy_config_mutex);
 }
 
-void fw_flush_transactions(struct fw_card *card)
-{
-	struct fw_transaction *t, *next;
-	struct list_head list;
-	unsigned long flags;
-
-	INIT_LIST_HEAD(&list);
-	spin_lock_irqsave(&card->lock, flags);
-	list_splice_init(&card->transaction_list, &list);
-	card->tlabel_mask = 0;
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	list_for_each_entry_safe(t, next, &list, link) {
-		card->driver->cancel_packet(card, &t->packet);
-
-		/*
-		 * At this point cancel_packet will never call the
-		 * transaction callback, since we just took all the
-		 * transactions out of the list.  So do it here.
-		 */
-		t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
-	}
-}
-
 static struct fw_address_handler *lookup_overlapping_address_handler(
 	struct list_head *list, unsigned long long offset, size_t length)
 {
@@ -841,7 +843,7 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
 	spin_lock_irqsave(&card->lock, flags);
 	list_for_each_entry(t, &card->transaction_list, link) {
 		if (t->node_id == source && t->tlabel == tlabel) {
-			list_del(&t->link);
+			list_del_init(&t->link);
 			card->tlabel_mask &= ~(1ULL << t->tlabel);
 			break;
 		}
@@ -883,6 +885,8 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
 		break;
 	}
 
+	del_timer_sync(&t->split_timeout_timer);
+
 	/*
 	 * The response handler may be executed while the request handler
 	 * is still pending.  Cancel the request handler.