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 | ||
