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/firewire/fw-card.c | |
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/firewire/fw-card.c')
-rw-r--r-- | drivers/firewire/fw-card.c | 18 |
1 files changed, 15 insertions, 3 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 | } |