diff options
author | Jay Fenlason <fenlason@redhat.com> | 2008-11-29 11:44:57 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-01-04 17:50:37 -0500 |
commit | 0fa1986f3a6c385b3bca0b6a051c30e548bda30d (patch) | |
tree | 5b61ce9579a520f89bc4c000bfe3496e58d4f47a /drivers | |
parent | 2cc489c21338950c2b4097dec48864bdf7b30f1b (diff) |
firewire: improve refcounting of fw_card
Take a reference to the card whenever fw_card_bm_work() is scheduled on
that card and release it when the work is done. This allows us to
remove the cancel_delayed_work_sync() in fw_core_remove_card().
Signed-off-by: Jay Fenlason <fenlason@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (patch update)
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firewire/fw-card.c | 18 | ||||
-rw-r--r-- | drivers/firewire/fw-device.c | 6 | ||||
-rw-r--r-- | drivers/firewire/fw-topology.c | 2 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.h | 2 |
4 files changed, 21 insertions, 7 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index c7760794de0d..799f94424c8a 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c | |||
@@ -189,6 +189,17 @@ static const char gap_count_table[] = { | |||
189 | 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 | 189 | 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 |
190 | }; | 190 | }; |
191 | 191 | ||
192 | void | ||
193 | fw_schedule_bm_work(struct fw_card *card, unsigned long delay) | ||
194 | { | ||
195 | int scheduled; | ||
196 | |||
197 | fw_card_get(card); | ||
198 | scheduled = schedule_delayed_work(&card->work, delay); | ||
199 | if (!scheduled) | ||
200 | fw_card_put(card); | ||
201 | } | ||
202 | |||
192 | static void | 203 | static void |
193 | fw_card_bm_work(struct work_struct *work) | 204 | fw_card_bm_work(struct work_struct *work) |
194 | { | 205 | { |
@@ -206,7 +217,7 @@ fw_card_bm_work(struct work_struct *work) | |||
206 | 217 | ||
207 | if (local_node == NULL) { | 218 | if (local_node == NULL) { |
208 | spin_unlock_irqrestore(&card->lock, flags); | 219 | spin_unlock_irqrestore(&card->lock, flags); |
209 | return; | 220 | goto out_put_card; |
210 | } | 221 | } |
211 | fw_node_get(local_node); | 222 | fw_node_get(local_node); |
212 | fw_node_get(root_node); | 223 | fw_node_get(root_node); |
@@ -280,7 +291,7 @@ fw_card_bm_work(struct work_struct *work) | |||
280 | * this task 100ms from now. | 291 | * this task 100ms from now. |
281 | */ | 292 | */ |
282 | spin_unlock_irqrestore(&card->lock, flags); | 293 | spin_unlock_irqrestore(&card->lock, flags); |
283 | schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); | 294 | fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 10)); |
284 | goto out; | 295 | goto out; |
285 | } | 296 | } |
286 | 297 | ||
@@ -355,6 +366,8 @@ fw_card_bm_work(struct work_struct *work) | |||
355 | fw_device_put(root_device); | 366 | fw_device_put(root_device); |
356 | fw_node_put(root_node); | 367 | fw_node_put(root_node); |
357 | fw_node_put(local_node); | 368 | fw_node_put(local_node); |
369 | out_put_card: | ||
370 | fw_card_put(card); | ||
358 | } | 371 | } |
359 | 372 | ||
360 | static void | 373 | static void |
@@ -510,7 +523,6 @@ fw_core_remove_card(struct fw_card *card) | |||
510 | fw_card_put(card); | 523 | fw_card_put(card); |
511 | wait_for_completion(&card->done); | 524 | wait_for_completion(&card->done); |
512 | 525 | ||
513 | cancel_delayed_work_sync(&card->work); | ||
514 | WARN_ON(!list_empty(&card->transaction_list)); | 526 | WARN_ON(!list_empty(&card->transaction_list)); |
515 | del_timer_sync(&card->flush_timer); | 527 | del_timer_sync(&card->flush_timer); |
516 | } | 528 | } |
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 31b6c74d34df..c173be383725 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c | |||
@@ -689,7 +689,7 @@ static void fw_device_init(struct work_struct *work) | |||
689 | fw_notify("giving up on config rom for node id %x\n", | 689 | fw_notify("giving up on config rom for node id %x\n", |
690 | device->node_id); | 690 | device->node_id); |
691 | if (device->node == device->card->root_node) | 691 | if (device->node == device->card->root_node) |
692 | schedule_delayed_work(&device->card->work, 0); | 692 | fw_schedule_bm_work(device->card, 0); |
693 | fw_device_release(&device->device); | 693 | fw_device_release(&device->device); |
694 | } | 694 | } |
695 | return; | 695 | return; |
@@ -758,7 +758,7 @@ static void fw_device_init(struct work_struct *work) | |||
758 | * pretty harmless. | 758 | * pretty harmless. |
759 | */ | 759 | */ |
760 | if (device->node == device->card->root_node) | 760 | if (device->node == device->card->root_node) |
761 | schedule_delayed_work(&device->card->work, 0); | 761 | fw_schedule_bm_work(device->card, 0); |
762 | 762 | ||
763 | return; | 763 | return; |
764 | 764 | ||
@@ -892,7 +892,7 @@ static void fw_device_refresh(struct work_struct *work) | |||
892 | fw_device_shutdown(work); | 892 | fw_device_shutdown(work); |
893 | out: | 893 | out: |
894 | if (node_id == card->root_node->node_id) | 894 | if (node_id == card->root_node->node_id) |
895 | schedule_delayed_work(&card->work, 0); | 895 | fw_schedule_bm_work(card, 0); |
896 | } | 896 | } |
897 | 897 | ||
898 | void fw_node_event(struct fw_card *card, struct fw_node *node, int event) | 898 | void fw_node_event(struct fw_card *card, struct fw_node *node, int event) |
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 5e204713002d..7687dca1a690 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c | |||
@@ -530,7 +530,7 @@ fw_core_handle_bus_reset(struct fw_card *card, | |||
530 | smp_wmb(); | 530 | smp_wmb(); |
531 | card->generation = generation; | 531 | card->generation = generation; |
532 | card->reset_jiffies = jiffies; | 532 | card->reset_jiffies = jiffies; |
533 | schedule_delayed_work(&card->work, 0); | 533 | fw_schedule_bm_work(card, 0); |
534 | 534 | ||
535 | local_node = build_tree(card, self_ids, self_id_count); | 535 | local_node = build_tree(card, self_ids, self_id_count); |
536 | 536 | ||
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 839466f0a795..0497a18dc59e 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
@@ -278,6 +278,8 @@ static inline void fw_card_put(struct fw_card *card) | |||
278 | kref_put(&card->kref, fw_card_release); | 278 | kref_put(&card->kref, fw_card_release); |
279 | } | 279 | } |
280 | 280 | ||
281 | extern void fw_schedule_bm_work(struct fw_card *card, unsigned long delay); | ||
282 | |||
281 | /* | 283 | /* |
282 | * The iso packet format allows for an immediate header/payload part | 284 | * The iso packet format allows for an immediate header/payload part |
283 | * stored in 'header' immediately after the packet info plus an | 285 | * stored in 'header' immediately after the packet info plus an |