diff options
-rw-r--r-- | drivers/firewire/core-card.c | 11 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 70 | ||||
-rw-r--r-- | drivers/firewire/core.h | 1 | ||||
-rw-r--r-- | include/linux/firewire.h | 3 |
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 | ||
411 | static 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 | |||
418 | void fw_card_initialize(struct fw_card *card, | 410 | void 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 | } |
564 | EXPORT_SYMBOL(fw_core_remove_card); | 553 | EXPORT_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 | } |
122 | EXPORT_SYMBOL(fw_cancel_transaction); | 123 | EXPORT_SYMBOL(fw_cancel_transaction); |
123 | 124 | ||
125 | static 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 | |||
124 | static void transmit_complete_callback(struct fw_packet *packet, | 150 | static 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 | ||
411 | void 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 | |||
435 | static struct fw_address_handler *lookup_overlapping_address_handler( | 437 | static 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); | |||
220 | void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); | 220 | void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); |
221 | void fw_fill_response(struct fw_packet *response, u32 *request_header, | 221 | void 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); |
223 | void fw_flush_transactions(struct fw_card *card); | ||
224 | void fw_send_phy_config(struct fw_card *card, | 223 | void 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 | ||