Commit 410cf2bd3dc6ec1ed9e1b36b25b9d7aa927ed14e

Authored by Clemens Ladisch
Committed by Stefan Richter
1 parent 693a50b511

firewire: use split transaction timeout only for split transactions

Instead of starting the split transaction timeout timer when any request
is submitted, start it only when the destination's ACK_PENDING has been
received.  This prevents us from using a timeout that is too short, and,
if the controller's AT queue is emptying very slowly, from cancelling
a packet that has not yet been sent.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

Showing 2 changed files with 33 additions and 14 deletions Side-by-side Diff

drivers/firewire/core-transaction.c
... ... @@ -72,6 +72,15 @@
72 72 #define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23))
73 73 #define PHY_IDENTIFIER(id) ((id) << 30)
74 74  
  75 +/* returns 0 if the split timeout handler is already running */
  76 +static int try_cancel_split_timeout(struct fw_transaction *t)
  77 +{
  78 + if (t->is_split_transaction)
  79 + return del_timer(&t->split_timeout_timer);
  80 + else
  81 + return 1;
  82 +}
  83 +
75 84 static int close_transaction(struct fw_transaction *transaction,
76 85 struct fw_card *card, int rcode)
77 86 {
... ... @@ -81,7 +90,7 @@
81 90 spin_lock_irqsave(&card->lock, flags);
82 91 list_for_each_entry(t, &card->transaction_list, link) {
83 92 if (t == transaction) {
84   - if (!del_timer(&t->split_timeout_timer)) {
  93 + if (!try_cancel_split_timeout(t)) {
85 94 spin_unlock_irqrestore(&card->lock, flags);
86 95 goto timed_out;
87 96 }
88 97  
... ... @@ -141,16 +150,28 @@
141 150 card->tlabel_mask &= ~(1ULL << t->tlabel);
142 151 spin_unlock_irqrestore(&card->lock, flags);
143 152  
144   - card->driver->cancel_packet(card, &t->packet);
145   -
146   - /*
147   - * At this point cancel_packet will never call the transaction
148   - * callback, since we just took the transaction out of the list.
149   - * So do it here.
150   - */
151 153 t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
152 154 }
153 155  
  156 +static void start_split_transaction_timeout(struct fw_transaction *t,
  157 + struct fw_card *card)
  158 +{
  159 + unsigned long flags;
  160 +
  161 + spin_lock_irqsave(&card->lock, flags);
  162 +
  163 + if (list_empty(&t->link) || WARN_ON(t->is_split_transaction)) {
  164 + spin_unlock_irqrestore(&card->lock, flags);
  165 + return;
  166 + }
  167 +
  168 + t->is_split_transaction = true;
  169 + mod_timer(&t->split_timeout_timer,
  170 + jiffies + card->split_timeout_jiffies);
  171 +
  172 + spin_unlock_irqrestore(&card->lock, flags);
  173 +}
  174 +
154 175 static void transmit_complete_callback(struct fw_packet *packet,
155 176 struct fw_card *card, int status)
156 177 {
... ... @@ -162,7 +183,7 @@
162 183 close_transaction(t, card, RCODE_COMPLETE);
163 184 break;
164 185 case ACK_PENDING:
165   - t->timestamp = packet->timestamp;
  186 + start_split_transaction_timeout(t, card);
166 187 break;
167 188 case ACK_BUSY_X:
168 189 case ACK_BUSY_A:
169 190  
... ... @@ -349,11 +370,9 @@
349 370 t->node_id = destination_id;
350 371 t->tlabel = tlabel;
351 372 t->card = card;
  373 + t->is_split_transaction = false;
352 374 setup_timer(&t->split_timeout_timer,
353 375 split_transaction_timeout_callback, (unsigned long)t);
354   - /* FIXME: start this timer later, relative to t->timestamp */
355   - mod_timer(&t->split_timeout_timer,
356   - jiffies + card->split_timeout_jiffies);
357 376 t->callback = callback;
358 377 t->callback_data = callback_data;
359 378  
... ... @@ -926,7 +945,7 @@
926 945 spin_lock_irqsave(&card->lock, flags);
927 946 list_for_each_entry(t, &card->transaction_list, link) {
928 947 if (t->node_id == source && t->tlabel == tlabel) {
929   - if (!del_timer(&t->split_timeout_timer)) {
  948 + if (!try_cancel_split_timeout(t)) {
930 949 spin_unlock_irqrestore(&card->lock, flags);
931 950 goto timed_out;
932 951 }
include/linux/firewire.h
... ... @@ -302,9 +302,9 @@
302 302 struct fw_transaction {
303 303 int node_id; /* The generation is implied; it is always the current. */
304 304 int tlabel;
305   - int timestamp;
306 305 struct list_head link;
307 306 struct fw_card *card;
  307 + bool is_split_transaction;
308 308 struct timer_list split_timeout_timer;
309 309  
310 310 struct fw_packet packet;