aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/core-card.c11
-rw-r--r--drivers/firewire/core-transaction.c70
-rw-r--r--drivers/firewire/core.h1
-rw-r--r--include/linux/firewire.h3
4 files changed, 39 insertions, 46 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 42cf911b73cf..9dcb30466ec0 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -30,7 +30,6 @@
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/mutex.h> 31#include <linux/mutex.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33#include <linux/timer.h>
34#include <linux/workqueue.h> 33#include <linux/workqueue.h>
35 34
36#include <asm/atomic.h> 35#include <asm/atomic.h>
@@ -408,13 +407,6 @@ static void fw_card_bm_work(struct work_struct *work)
408 fw_card_put(card); 407 fw_card_put(card);
409} 408}
410 409
411static void flush_timer_callback(unsigned long data)
412{
413 struct fw_card *card = (struct fw_card *)data;
414
415 fw_flush_transactions(card);
416}
417
418void fw_card_initialize(struct fw_card *card, 410void fw_card_initialize(struct fw_card *card,
419 const struct fw_card_driver *driver, 411 const struct fw_card_driver *driver,
420 struct device *device) 412 struct device *device)
@@ -433,8 +425,6 @@ void fw_card_initialize(struct fw_card *card,
433 init_completion(&card->done); 425 init_completion(&card->done);
434 INIT_LIST_HEAD(&card->transaction_list); 426 INIT_LIST_HEAD(&card->transaction_list);
435 spin_lock_init(&card->lock); 427 spin_lock_init(&card->lock);
436 setup_timer(&card->flush_timer,
437 flush_timer_callback, (unsigned long)card);
438 428
439 card->local_node = NULL; 429 card->local_node = NULL;
440 430
@@ -559,7 +549,6 @@ void fw_core_remove_card(struct fw_card *card)
559 wait_for_completion(&card->done); 549 wait_for_completion(&card->done);
560 550
561 WARN_ON(!list_empty(&card->transaction_list)); 551 WARN_ON(!list_empty(&card->transaction_list));
562 del_timer_sync(&card->flush_timer);
563} 552}
564EXPORT_SYMBOL(fw_core_remove_card); 553EXPORT_SYMBOL(fw_core_remove_card);
565 554
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,
81 spin_lock_irqsave(&card->lock, flags); 81 spin_lock_irqsave(&card->lock, flags);
82 list_for_each_entry(t, &card->transaction_list, link) { 82 list_for_each_entry(t, &card->transaction_list, link) {
83 if (t == transaction) { 83 if (t == transaction) {
84 list_del(&t->link); 84 list_del_init(&t->link);
85 card->tlabel_mask &= ~(1ULL << t->tlabel); 85 card->tlabel_mask &= ~(1ULL << t->tlabel);
86 break; 86 break;
87 } 87 }
@@ -89,6 +89,7 @@ static int close_transaction(struct fw_transaction *transaction,
89 spin_unlock_irqrestore(&card->lock, flags); 89 spin_unlock_irqrestore(&card->lock, flags);
90 90
91 if (&t->link != &card->transaction_list) { 91 if (&t->link != &card->transaction_list) {
92 del_timer_sync(&t->split_timeout_timer);
92 t->callback(card, rcode, NULL, 0, t->callback_data); 93 t->callback(card, rcode, NULL, 0, t->callback_data);
93 return 0; 94 return 0;
94 } 95 }
@@ -121,6 +122,31 @@ int fw_cancel_transaction(struct fw_card *card,
121} 122}
122EXPORT_SYMBOL(fw_cancel_transaction); 123EXPORT_SYMBOL(fw_cancel_transaction);
123 124
125static void split_transaction_timeout_callback(unsigned long data)
126{
127 struct fw_transaction *t = (struct fw_transaction *)data;
128 struct fw_card *card = t->card;
129 unsigned long flags;
130
131 spin_lock_irqsave(&card->lock, flags);
132 if (list_empty(&t->link)) {
133 spin_unlock_irqrestore(&card->lock, flags);
134 return;
135 }
136 list_del(&t->link);
137 card->tlabel_mask &= ~(1ULL << t->tlabel);
138 spin_unlock_irqrestore(&card->lock, flags);
139
140 card->driver->cancel_packet(card, &t->packet);
141
142 /*
143 * At this point cancel_packet will never call the transaction
144 * callback, since we just took the transaction out of the list.
145 * So do it here.
146 */
147 t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
148}
149
124static void transmit_complete_callback(struct fw_packet *packet, 150static void transmit_complete_callback(struct fw_packet *packet,
125 struct fw_card *card, int status) 151 struct fw_card *card, int status)
126{ 152{
@@ -294,13 +320,6 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
294 int tlabel; 320 int tlabel;
295 321
296 /* 322 /*
297 * Bump the flush timer up 100ms first of all so we
298 * don't race with a flush timer callback.
299 */
300
301 mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10));
302
303 /*
304 * Allocate tlabel from the bitmap and put the transaction on 323 * Allocate tlabel from the bitmap and put the transaction on
305 * the list while holding the card spinlock. 324 * the list while holding the card spinlock.
306 */ 325 */
@@ -316,6 +335,11 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
316 335
317 t->node_id = destination_id; 336 t->node_id = destination_id;
318 t->tlabel = tlabel; 337 t->tlabel = tlabel;
338 t->card = card;
339 setup_timer(&t->split_timeout_timer,
340 split_transaction_timeout_callback, (unsigned long)t);
341 /* FIXME: start this timer later, relative to t->timestamp */
342 mod_timer(&t->split_timeout_timer, jiffies + DIV_ROUND_UP(HZ, 10));
319 t->callback = callback; 343 t->callback = callback;
320 t->callback_data = callback_data; 344 t->callback_data = callback_data;
321 345
@@ -361,11 +385,13 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
361 struct transaction_callback_data d; 385 struct transaction_callback_data d;
362 struct fw_transaction t; 386 struct fw_transaction t;
363 387
388 init_timer_on_stack(&t.split_timeout_timer);
364 init_completion(&d.done); 389 init_completion(&d.done);
365 d.payload = payload; 390 d.payload = payload;
366 fw_send_request(card, &t, tcode, destination_id, generation, speed, 391 fw_send_request(card, &t, tcode, destination_id, generation, speed,
367 offset, payload, length, transaction_callback, &d); 392 offset, payload, length, transaction_callback, &d);
368 wait_for_completion(&d.done); 393 wait_for_completion(&d.done);
394 destroy_timer_on_stack(&t.split_timeout_timer);
369 395
370 return d.rcode; 396 return d.rcode;
371} 397}
@@ -408,30 +434,6 @@ void fw_send_phy_config(struct fw_card *card,
408 mutex_unlock(&phy_config_mutex); 434 mutex_unlock(&phy_config_mutex);
409} 435}
410 436
411void fw_flush_transactions(struct fw_card *card)
412{
413 struct fw_transaction *t, *next;
414 struct list_head list;
415 unsigned long flags;
416
417 INIT_LIST_HEAD(&list);
418 spin_lock_irqsave(&card->lock, flags);
419 list_splice_init(&card->transaction_list, &list);
420 card->tlabel_mask = 0;
421 spin_unlock_irqrestore(&card->lock, flags);
422
423 list_for_each_entry_safe(t, next, &list, link) {
424 card->driver->cancel_packet(card, &t->packet);
425
426 /*
427 * At this point cancel_packet will never call the
428 * transaction callback, since we just took all the
429 * transactions out of the list. So do it here.
430 */
431 t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
432 }
433}
434
435static struct fw_address_handler *lookup_overlapping_address_handler( 437static struct fw_address_handler *lookup_overlapping_address_handler(
436 struct list_head *list, unsigned long long offset, size_t length) 438 struct list_head *list, unsigned long long offset, size_t length)
437{ 439{
@@ -841,7 +843,7 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
841 spin_lock_irqsave(&card->lock, flags); 843 spin_lock_irqsave(&card->lock, flags);
842 list_for_each_entry(t, &card->transaction_list, link) { 844 list_for_each_entry(t, &card->transaction_list, link) {
843 if (t->node_id == source && t->tlabel == tlabel) { 845 if (t->node_id == source && t->tlabel == tlabel) {
844 list_del(&t->link); 846 list_del_init(&t->link);
845 card->tlabel_mask &= ~(1ULL << t->tlabel); 847 card->tlabel_mask &= ~(1ULL << t->tlabel);
846 break; 848 break;
847 } 849 }
@@ -883,6 +885,8 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
883 break; 885 break;
884 } 886 }
885 887
888 del_timer_sync(&t->split_timeout_timer);
889
886 /* 890 /*
887 * The response handler may be executed while the request handler 891 * The response handler may be executed while the request handler
888 * is still pending. Cancel the request handler. 892 * is still pending. Cancel the request handler.
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 7a9759bf6837..0ecfcd95f4c5 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -220,7 +220,6 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
220void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); 220void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
221void fw_fill_response(struct fw_packet *response, u32 *request_header, 221void fw_fill_response(struct fw_packet *response, u32 *request_header,
222 int rcode, void *payload, size_t length); 222 int rcode, void *payload, size_t length);
223void fw_flush_transactions(struct fw_card *card);
224void fw_send_phy_config(struct fw_card *card, 223void fw_send_phy_config(struct fw_card *card,
225 int node_id, int generation, int gap_count); 224 int node_id, int generation, int gap_count);
226 225
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index a527d73f9966..72e2b8ac2a5a 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -87,7 +87,6 @@ struct fw_card {
87 int current_tlabel; 87 int current_tlabel;
88 u64 tlabel_mask; 88 u64 tlabel_mask;
89 struct list_head transaction_list; 89 struct list_head transaction_list;
90 struct timer_list flush_timer;
91 unsigned long reset_jiffies; 90 unsigned long reset_jiffies;
92 91
93 unsigned long long guid; 92 unsigned long long guid;
@@ -288,6 +287,8 @@ struct fw_transaction {
288 int tlabel; 287 int tlabel;
289 int timestamp; 288 int timestamp;
290 struct list_head link; 289 struct list_head link;
290 struct fw_card *card;
291 struct timer_list split_timeout_timer;
291 292
292 struct fw_packet packet; 293 struct fw_packet packet;
293 294